表与表之间的关系: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修改AlertDialog宽和高以及设置AlertDialog的背景

    不知道你们试过了吗,AlertDialog在我们给他设置我们自己的布局的时候他的宽度不论我们怎么设置他都是不变的,要想改变宽和高我们可以动态的去修改他的宽度好高度 直接上代码 // 1. 布局文件转换 ...

  2. Android - 通过真实案例学习解内存泄漏问题,最终发现Android原生Bug

    作为一个Android新手小白,刚到新公司,最近的工作就是在学习解各类Bug.转型之初,面临各种新知识,会有压力,但是学习的过程是快乐的. 上周刚遇上一类bug,就是应用的内存泄漏问题.最终通过前辈的 ...

  3. Spring实践系列-入门篇(一)

    本文主要介绍了在本地搭建并运行一个Spring应用,演示了Spring依赖注入的特性 1 环境搭建 1.1 Maven依赖 目前只用到依赖注入的功能,故以下三个包已满足使用. <properti ...

  4. adobe air ane 中有的java class 打包 apk 后却没有了报NoClassDefFoundError ,ClassNotFoundException

    apache flex sdk 手机项目 09-18 10:34:55.030: E/AndroidRuntime(19513): FATAL EXCEPTION: main 09-18 10:34: ...

  5. Struts2_用ModelDriven接收参数

    通过实现 ModelDriven 接口来接收请求参数,这种方法用的比较少,一般还是用前两种. 请求: <a href="user/user!add?name=xiaoer&ag ...

  6. CSS:响应式下的折叠菜单(条纹式)

    原文:CSS: Responsive Navigation Menu 译文:CSS:响应式导航菜单 译者:dwqs 写在之前,关于如何制作响应式的下拉菜单:响应式下的下拉菜单 之前,我写了一篇关于怎么 ...

  7. Graylog安装操作

    Graylog安装操作 实验环境centos7.5系统  mem:4-8G       disk:50G 关闭selinux以及firewalld 一.准备环境 1.1.java环境 下载java的j ...

  8. Kubernetes解决了Docker使用中的哪些问题?

    kubernetes是谷歌开源的容器集群管理系统,是Google多年大规模容器管理技术Borg的开源版本 (1)基于容器的应用部署.维护和滚动升级 (2)网络,建立容器之间的通信子网如隧道.路由等,解 ...

  9. 2018.7.30 Oracle的Blog数据库类型读取和存

    package com.lanqiao.shopping.test; import java.io.BufferedInputStream; import java.io.BufferedOutput ...

  10. Design and Implementation of Global Path Planning System for Unmanned Surface Vehicle among Multiple Task Points

    Design and Implementation of Global Path Planning System for Unmanned Surface Vehicle among Multiple ...