表与表之间的关系:1:1  1:多  多:多

  功能需求决定表关系

  

  此处的表关系为:品牌表:商品表=1:多

  1、首先在表结构上关联,在多的表(商品表)添加一个字段,关联一的表(品牌表)的ID(主键)

    添加字段:ALTE TABLE p39_goods ADD brand_id mediumint unsigned not null default '0' comment '品牌id';

    注:因为需求【有可能根据品牌搜商品】,所以在商品表加上品牌id索引

    添加索引: ALTER TABLE p39_goods ADD INDEX brand_id(brand_id);

2、程序代码上关联

添加商品时选择品牌

2.1在控制器GoodsController.class.php/add()中取出所有品牌

2.2在表单/Adimin/View/Goods/add.html制作下拉框

  $brandData:为品牌表中取出

2.3提交表单时,把品牌id保存到商品表的brand_id字段,修改商品模型GoodsModel.class.php允许接收表单的品牌id字段

商品列表中显示品牌信息

2.4在Goods/lst.html中添加列  

  $data:为商品表中取出

  注:因为商品表中中保存的为品牌id,显示id没有意义,因此在取商品表数据$data时,应连表查询出品牌表中brand_name的数据

2.5取商品信息时连表取出品牌名称

  修改商品模型GoodsModel.class.php中的search方法

  __BRAND__:可以避免当表前缀发生改变时,连表失效【tp提供的】

  SQL多表连接查询

注:多表查询建议给表取别名,以免发生不同表同字段的错误,导致显示、查询失败等。此处有一个需要注意的地方【错误8

<?php
namespace Admin\Model;
use Think\Model; class GoodsModel extends Model
{
//添加调用create方法允许接收的字段
protected $insertFields = 'goods_name,market_price,shop_price,is_on_sale,goods_desc,brand_id';
//修改调用create方法允许接收的字段
protected $updateFields = 'id,goods_name,market_price,shop_price,is_on_sale,goods_desc,brand_id,member_price'; //定义验证规则 validate:TP模型层提供的一种数据验证方法
//a.静态方式:在模型类里面通过$_validate属性定义验证规则。b.动态方式:使用模型类的validate方法动态创建自动验证规则
//定义好验证规则后,就可以在使用create方法创建数据对象的时候自动调用
protected $_validate = array(
array('goods_name', 'require', '商品名称不能为空!', '1'),
array('market_price', 'currency', '市场价格必须是货币!', '1'),
array('shop_price', 'currency', '本店价格必须是货币类型!', '1'),
); //钩子方法_before_insert:添加前插入,在添加前会自动调用
//第一个参数:表单中即将要被插入数据库中的数据=>数组
//&按引用传递:函数外部的变量的值要在函数内部修改的话,必须按引用传递,除非传递的为对象,因为对象默认按引用传递
protected function _before_insert(&$data, $option)
{
$id = $option['where']['id']; //要修改的商品的ID /**************处理LOGO******************/
//判断有没有选择图片
if($_FILES['logo']['error'] == 0)
{
$ret = uploadOne('logo', 'Goods', array(
array(700, 700),
array(350, 350),
array(130, 130),
array(50, 50),
));
$data['logo'] = $ret['images'][0];
$data['mbig_logo'] = $ret['images'][1];
$data['big_logo'] = $ret['images'][2];
$data['mid_logo'] = $ret['images'][3];
$data['sm_logo'] = $ret['images'][4];
}
//获取当前时间并添加到表单中,这样就会插入数据库中
$data['addtime'] = date('Y-m-d H:i:s', time()); //过滤这个字段 【必须对所有输入内容进行过滤】
$data['goods_desc'] = removeXSS($_POST['goods_desc']);
} //钩子方法_before_update:更新前插入,在添加前会自动调用
protected function _before_update(&$data, $option)
{
/* var_dump($data);
var_dump($option);
die(); */
$id = $option['where']['id']; //要修改的商品的ID /**************处理LOGO******************/
//判断有没有选择图片
if($_FILES['logo']['error'] == 0)
{
$ret = uploadOne('logo', 'Goods', array(
array(700, 700),
array(350, 350),
array(130, 130),
array(50, 50),
));
$data['logo'] = $ret['images'][0];
$data['mbig_logo'] = $ret['images'][1];
$data['big_logo'] = $ret['images'][2];
$data['mid_logo'] = $ret['images'][3];
$data['sm_logo'] = $ret['images'][4]; //先查询出原来的图片的路径
$oldLogo = $this->field('logo,mbig_logo,big_logo,mid_logo,sm_logo')->find($id);
//从硬盘上删除图片
deleteImage($oldLogo);
}
//过滤这个字段 【必须对所有输入内容进行过滤】
$data['goods_desc'] = removeXSS($_POST['goods_desc']);
}
/* protected function _after_update(&$data, $option)
{
var_dump($data);
var_dump($option);
die();
} */ //钩子方法_before_delete:删除前的操作
protected function _before_delete($option)
{
$id = $option['where']['id']; //要删除的商品的ID
//先查询出原来的图片的路径
$oldLogo = $this->field('logo,mbig_logo,big_logo,mid_logo,sm_logo')->find($id); deleteImage($oldLogo);
} //钩子方法_after_insert:添加操作成功后执行
protected function _after_insert($data, $option)
{
$mp = I('post.member_price'); //接收post提交过来的会员价格数据
$mpModel = D('member_price');
foreach ($mp as $k => $v)
{
$_v = (float)$v; //强制转为浮点型,以免插入字符等错误数据
//设置会员价格>0就插入到表中
if($_v > 0)
{
$mpModel->add(array(
'price' => $_v,
'level_id' => $k, //级别Id
'goods_id' => $data['id'],
));
}
}
} /**
*实现翻页、搜索、排序
*
*/
public function search($perPage = 5) //$perPage控制显示条数
{
/***********搜索(获取get提交的数据)************/
$where =array(); //空的where条件
//商品名称
$gn = I('get.gn');
if($gn)
$where['a.goods_name'] = array('like', "%$gn%"); //WHERE goods_name LIKE '%$gn%'
//品牌
$brandId = I('get.brand_id');
if($brandId)
$where['a.brand_id'] = array('eq', "$brandId"); //WHERE goods_name LIKE '%$gn%'
//市场价格
$fp = I('get.fp');
$tp = I('get.tp');
if($fp && $tp)
$where['a.shop_price'] = array('between', array($fp, $tp)); //WHERE shop_price BETWEEN $fp AND $tp
elseif($fp)
$where['a.shop_price'] = array('egt', $fp); //WHERE shop_price >= $fp
elseif($tp)
$where['a.shop_price'] = array('elt', $tp); //WHERE shop_price <= $tp
//是否上架
$ios = I('get.ios');
if($ios)
$where['a.is_on_sale'] = array('eq', $ios); //WHERE is_on_sale = $ios
//添加时间
$fa = I('get.fa');
$ta = I('get.ta');
if($fa && $ta)
$where['a.addtime'] = array('between', array($fa, $ta)); //WHERE addtime BETWEEN $fa ADD $ta
elseif($fa)
$where['a.addtime'] = array('egt', $fa); //WHERE addtime >= $fa
elseif($ta)
$where['a.addtime'] = array('elt', $ta); //WHERE addtime <= $ta /***********翻页**********/
//取出总的记录数
$count = $this->alias('a')->where($where)->count();
//生成翻页类的对象
$pageObj = new \Think\Page($count, $perPage);
//设置样式
$pageObj->setConfig('next', '下一页');
$pageObj->setConfig('prev', '上一页');
//生成页面下面显示的上一页、下一页的字符串
$pageString = $pageObj->show(); /**********排序********************/
$orderby = 'a.id'; //默认的排序字段
$orderway = 'desc'; //默认的排序方式(降序)
$odby = I('get.odby');
if($odby)
{
if($odby == 'id_asc') //时间升序,id为自增
$orderway = 'asc';
elseif($odby == 'price_desc') //价格降序(默认降序)
$orderby = 'a.shop_price';
elseif($odby == 'price_asc') //价格升序
{
$orderby = 'a.shop_price';
$orderway = 'asc';
}
} /**********取某一页的数据**********/
/***
* SELECT a.*,b.brand_name FROM p39_goods a LEFT JOIN p39_brand b ON a.brand_id=b.id;
**/ $data = $this->order("$orderby $orderway")
->field('a.*, b.brand_name')
->alias('a') //加别名
->join('LEFT JOIN __BRAND__ b ON a.brand_id=b.id')
->where($where)
->limit($pageObj->firstRow.','.$pageObj->listRows)
->select(); /************返回数据$data*************/
return array(
'data' => $data, //数据
'page' => $pageString, //翻页字符串
);
} }
?>

GoodsModel.class.php

外连与内连查询的区别商城项目多用外连

  外连:SELECT a.*,b.brand_name FROM p39_goods a LEFT JOIN p39_brand b ON a.brand_id=b.id;

    主表数据一定能取出来,无论是否有关联;left join:左表为主表;

    内连:SELECT a.*,b.brand_name FROM p39_goods a  JOIN p39_brand b ON a.brand_id=b.id;

       SELECT a.*,b.brand_name FROM p39_goods a, p39_brand b WHERE a.brand_id=b.id;

      只能取出两个表中有关联关系的数据,

则lst.html品牌显示处,可修改brand_id为brand_name,使之显示品牌名称

修改商品页面edit.html中显示品牌信息

2.6在控制器GoodsController.class.php/edit()中【此处会取出$data商品表和$brandData品牌表】

2.7制作下拉框,显示当前品牌为选定状态

 优化:下拉框函数

PHP.28-TP框架商城应用实例-后台5-多表操作-商品表与品牌表的更多相关文章

  1. PHP.31-TP框架商城应用实例-后台7-商品会员修改-页面优化,多表数据更新

    商品表修改功能 1.页面优化,类似添加页面 <layout name="layout" /> <div class="tab-div"> ...

  2. PHP.41-TP框架商城应用实例-后台16-商品属性2-AJAX添加、删除

     添加商品属性 思路:根据[后台15]类型表{id,type_name}与属性表{id,attr_name,attr_type,attr_option_values,type_id} 1.建表商品属性 ...

  3. PHP.38-TP框架商城应用实例-后台14-商品管理-商品扩展分类的删除、修改

    商品分类删除 1.删除商品时,根据商品id删除扩展分类表数据 商品扩展分类修改 1.在控制器GoodsController.class.php/edit()中根据商品id取出对应的所有扩展分类 2.在 ...

  4. PHP.24-TP框架商城应用实例-后台1-添加商品功能、钩子函数、在线编辑器、过滤XSS、上传图片并生成缩略图

    添加商品功能 1.创建商品控制器[C] /www.test.com/shop/Admin/Controller/GoodsController.class.php <?php namespace ...

  5. PHP.48-TP框架商城应用实例-后台23-权限管理-权限验证

    权限验证 1.登录控制器 2.通过tp验证码类生成验证码图片 3.在管理员模型增加登录验证规则 4.后台中所有的控制器必须先登录才能访问 思路:在访问任何一个控制器之前都判断一个session即可,= ...

  6. PHP.27-TP框架商城应用实例-后台4-使用Gii生成品牌表的代码

    Gii安装[GII适用于商城项目] 将Gii文件夹复到application 是,访问http://xx.com/index.php/gii Gii规则[Gii使用规则与建表规则密切相关] 1.建表字 ...

  7. PHP.44-TP框架商城应用实例-后台19-权限管理-RBAC需求分析

    RBAC:Role Based Access Control:基于角色的访问控制 需求分析:[类似效果如下图] 1.权限,角色,管理员 2.权限管理[无限级] 注意:权限会被分配给角色,而不是给管理员 ...

  8. PHP.43-TP框架商城应用实例-后台18-商品属性3-库存量管理

    库存量管理 思想:为商品的每个多选属性设置库存量!!要把多选属性排列组合分别指定库存量!! 效果如下:[由商品已经添加的属性决定] 1.建表goods_number{goods_id,goods_nu ...

  9. PHP.33-TP框架商城应用实例-后台9-商品相册-修改、删除(AJAX)

    商品相册图片删除 当商品删除时,把相册中的图片一并从硬盘和数据库中删除,根据商品id[因为每一张商品相片都会生成三张缩略图,所以删除时要将其缩略图一并删除] //钩子方法_before_delete: ...

随机推荐

  1. Android 编码风格规范,很赞哦

    1. 前言 这份文档参考了 Google Java 编程风格规范和 Google 官方 Android 编码风格规范.该文档仅供参考,只要形成一个统一的风格,见量知其意就可. 1.1 术语说明 在本文 ...

  2. PhoneGap&jQuery Mobile应用开发环境配置(For Android)

    关于移动应用为什么用PhoneGap和jQuery Mobile本文不再赘述,有兴趣的童鞋可以自行问“度娘”,有很多这方面的文章.本文主要介绍PhoneGap&jQuery Mobile移动应 ...

  3. Ubuntu、Windows 、Linux集合

    一.Ubuntu/Windows双系统修复引导   首先说明:在Windows存在的前提下安装Ubuntu(或者Ubuntu系列)是不需要修复引导的.因为grub会自动搜索存在硬盘中的系统.   而在 ...

  4. SQL查询某一字段重复的数据

    查询出重复记录 select * from 数据表 WHERE 重复记录字段 in ( select 重复记录字段 from  数据表 group by 重复记录字段 having count(重复记 ...

  5. ASP.NET写入和读取xml文件

    xml是一种可扩展标记语言,在电子计算机中,标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种的信息比如文章等.它可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进 ...

  6. 用AutoHotkey一键打开、激活、或隐藏Chrome(或其他软件)

    热键的效果: 1.Chrome没打开时,打开Chrome 2.Chrome已打开,未激活时,则激活Chrome 3.Chrome已激活,则隐藏Chrome 本来这种功能对AutoHotkey来说非常简 ...

  7. COGS 2075. [ZLXOI2015][异次元圣战III]ZLX的陨落

    ★★☆   输入文件:ThefallingofZLX.in   输出文件:ThefallingofZLX.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] 正当革命如火如 ...

  8. April 25 2017 Week 17 Tuesday

    Have you ever known the theory of chocie? There are a bunch of axiems, but there are only two thing ...

  9. Nagios监控ActiveMQ插件开发和部署注意事项

    前提,监控服务器是Ubuntu14 操作系统.被监控服务器是RHEL6.5 RHEL7 1.自定义插件可以使用bash.python等脚本来实现. 2.通过nrpe插件来实现监控服务器和被监控主机之间 ...

  10. Gym - 100004A 树的性质

    题目: 题意: 从节点 0 出发,把每一个节点都经过一遍,然后从一个节点回到学校. 由于有 n+1个节点,n条边,而且保证两两互相到达,那么这就是一个棵树. 于是,可以发现,如果从一个点出发,然后回到 ...