好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

在线商城表结构

在线商城表结构

李炎恢-在线商城第三季总结

 

1)      首先分析一下表结构 (数据库设计尤为重要)

①   管理员表mall_manage

 

②   管理员等级表mall_level

 

   解释:level为外键,为管理员等级(一对一)

③   用户表mall_user

 

④   用户收货地址表mall_address

 

解释:

1.用户的收货地址可以有多个,而只有一个是默认(selected=1);

2.这里的收货地址表并没有去关联用户表,其实可以关联一下;

⑤   商品类型表mall_nav

 

解释:

商品类型(商品栏目),这里支持无限极分类; 其中sid表示其分类id(为0表示顶级父类); 只有子类才可以关联商品品牌(多对多)等外表,顶级父类不可以关联; 而价格区间无论是子类还是父类都可关联(多对多)。(补充:更合理划分价格区间,应该由该类目下的最高价格与最低价格之间进行比对,然后再自动划分,不太应该由用户指定)

 

⑥   商品品牌表

 

⑦   商品属性表

 

解释:商品属性关联商品类型,原因是商品类型有限而固定,属性可以随时增减,属性关联类型更合理;(多对多)

⑧   商品价格区间表

 

⑨   商品表

 

解释:

1.商品goods_id-à商品类型nav_id (一对一)(补充:这里商品类型必须是子类)

2.商品goods_id-à商品品牌brand_id(一对一)(一个商品只属于一个品牌)

3.商品goods_id-à商品属性attr_id(一对多)(一个商品有多个属性)

4.关键字段说明:商品编号goods_sn、大缩略图thumbnail、小缩略图thumbnail2、本店价price_sale、市场价price_market、成本价price_cost、单位计量unit、重量weight、详细描述content、是否上架is_up、是否免邮费is_freight、库存量inventory、warn_inventory最小库存量(小于它,将会报库存警告)、发布时间date

 

⑩   订单表

 

解释:(说明,这里为了方便起见,并没有将用户表、用户收货地址表关联起来)

订单表order_id-àuser_id(一对一,该订单只能属于一个用户); 订单表order_id-àuser_address_id(一对一,该订单只能对应一个收货地址,可修改); 订单表order_id-à支付方式表pay_id(一对一,该订单只能对应一种支付方式,可修改); 订单表order_id-à配送方式表delivery_id(一对一,该订单只能对应一种配送方式,可修改) 补充:还有一个缺货处理方式表,该表是否需要建立,目前未知; 关键字段说明:用户备注text、缺货处理方式ps、订单编号ordernum、总价格price、商品详请goods(serialize序列化后存储)、订单状态order_state、配送状态order_delivery、支付状态order_pay、下单时间date

数据库名mall,一共10张表,如下:

 

数据库分析总结: 需要改进的地方有以下几点:

用户表应与用户收货地址表相关联,减小重复; 订单表应与用户收货地址表相关联,减少重复; 应建立支付方式表pay,再关联,满足三范式; 应建立配送方式表delivery,再关联,满足三范式; 其他还在整理中…

2)      然后,分析李炎恢第三季在线商城MVC框架(原理+实例)

 

①   其目录结构如下:

 

②   目录结构说明:

该架构使用smarty作为模板引擎,其对应目录smarty、cache、compile、view(修改自templates),分别是smarty核心文件、缓存目录、编译文件、模板文件(MVC称之为视图层); 其MVC结构,controller控制器、model模型层、view视图层、check验证层(隶属于model层,为model层服务,负责对请求数据,进行验证); 其他目录说明,ckeditor开源文本编辑器、configs配置文件、public公共类库(如工具类、图片处理类、文件上传类等)、uploads存放上传文件、index.php入口文件;

③   商城框架流程图(非常重要)

层次结构(李炎恢老师画)

 

---------------------------------------------------------------------------------------------------------------------

类结构(李炎恢老师画)

 

说明:上图在此你可能看不懂,下面会以实例说明之

④   其框架特点总结

单一入口,index.php,所有请求都通过index.php入口文件; 请求方式index.php?a=mamage&m=add (a表示action,m表示方法method),如上请求ManageAction()->add(); 实例化action,使用了简单工厂模式Factory::setAction()->run(),其原理是通过判断$_GET[‘a’]去实例化action; 执行m方法,Factory::setAction()->run(),在顶级父类Action的run()方法中,判断$_GET[‘m’],去执行相应的action方法; Action中持有model、smarty、redirect类的实例,使用了组合模式。调用model,对请求数据进行处理、验证数据、查询数据库等,smarty加载模板文件并解析生成缓存文件(加载视图),redirect负责页面跳转; Model中持有request、check、db类的实例,使用了组合模式。调用request对所请求的数据过滤,调用check验证请求数据,调用db查询数据库完成增删改查操作; 使用TPL类继承Smarty,然后修改Smarty和实现单例,使用了单例模式;这里面很多类都是用了单例模式,请注意; 其他说明,controller层中类命名为xxxAction.class.php,model层中类命名为xxxModel.class.php,check层中类命名为xxxCheck.class.php。 如ManageAction.class.php,ManageModel.class.php,ManageCheck.class.php

⑤   以管理员Manage模块中的添加管理员为例,详解执行流程:

首先交代一下本次操作会涉及到的目录及文件:

index.php configs/run.inc.php à 运行时index.php直接加载的文件 configs/profile.inc.php- à 系统配置文件 Smarty/Smarty.class.php- à Smarty模板引擎调用入口类 Public/几乎所有文件,其中较为重要Factory.class.php-à工厂类、TPL.class.php-à模板引擎类、DB.class.php-à数据库工具类、Redirect.class.php-à跳转类、Request.class.php-à请求处理类、Validate.class.php-à验证类、Tool.class.php-à工具类等 Controller/Action.class.php à 控制器顶级父类 Controller/ManageAction.class.php- à 管理员控制器类 Model/ManageModel.class.php à 管理员模型类 Model/LevelModel.class.php à 等级模型类 (此类是对等级表进行增删改查操作)

详细执行流程如下:以请求参数 http://localhost/Mall/index.php?a=manage&m=add ,注意这里的请求时通过点击新增管理员表单的submit按钮后,直奔的地址,此时会把用户名、密码、确认密码、等级等一起提交过来。故事就此展开……

首先服务器加载index.php;

里面只做了一件事,加载configs/run.inc.php

代码:

 1   require   dirname ( __FILE__ ).'/configs/run.inc.php';

然后run.inc.php文件里面做了以下主要操作:加载configs/profile.inc.php系统配置文件、加载Smarty/Smarty.class.php、自定义自动加载器_autoload()、调用Factory->setAction()实例化,由地址栏参数a=manage指定的ManageAction.class.php、最后再次调用Factory->setAction()->run(),即调用刚刚实例化的ManageAction对象的run()方法(这里的run()方法是继承自Action.class.php),执行相应的方法,即执行的完成操作是$ManageAction->add()操作;

关键性代码如下:(说明:以下只会贴出本次操作,该类下的相应方法,不是整个类)

Config/run.inc.php代码如下:

  1  <? php
   2  
  3   session_start  ();
   4  
  5   //  错误级别 
  6  
  7   error_reporting ( E_ALL  );
   8  
  9   //  网站根目录 
 10  
 11   define ('ROOT_PATH',  substr ( dirname ( __FILE__ ),0,-8 ));
  12  
 13   //  设置编码 
 14  
 15   header ('Content-Type: text/html;charset=utf-8' );
  16  
 17   //  设置时区 
 18  
 19  date_default_timezone_set('Asia/Shanghai' );
  20  
 21   //  引入Smarty配置文件 
 22  
 23   require  ROOT_PATH.'/configs/profile.inc.php' ;
  24  
 25   //  引入smarty引擎 
 26  
 27   require  ROOT_PATH.'/smarty/Smarty.class.php' ;
  28  
 29   //  自动加载类 
 30  
 31   function  __autoload( $className  ) {
  32  
 33   if  ( substr ( $className ,-6) == 'Action' ) {
  34  
 35              require  ROOT_PATH.'/controller/'. $className .'.class.php' ;
  36  
 37  }  else   if ( substr ( $className ,-5) == 'Model' ) {
  38  
 39              require  ROOT_PATH.'/model/'. $className .'.class.php' ;
  40  
 41  }  else   if  ( substr ( $className , -5) == 'Check' ) {
  42  
 43              require  ROOT_PATH.'/check/'. $className .'.class.php' ;
  44  
 45  }  else   {
  46  
 47              require  ROOT_PATH.'/public/'. $className .'.class.php' ;
  48  
 49   }
  50  
 51   }
  52  
 53   //  单入口 
 54  
 55  Factory::setAction()-> run();
  56  
 57  ?>

Factory.class.php代码如下:

  1   //  简单工厂类 
  2  
  3   class   Factory{
   4  
  5   private   static   $_obj  =  null  ;
   6  
  7   public   static   function   setAction() {
   8  
  9              $a  = self:: getA();
  10  
 11              if (! file_exists (ROOT_PATH.'/controller/'. $a .'Action.class.php'))  $a  = 'Index' ;
  12  
 13              eval ('self::$_obj = new '. ucfirst ( $a ).'Action();' );
  14  
 15              return  self:: $_obj  ;
  16  
 17   }
  18  
 19  }

Action.class.php代码如下:

  1   //  顶级控制器 
  2  
  3   class   Action {
   4  
  5   //  模板对象 
  6  
  7   protected   $tpl  =  null  ;
   8  
  9   //  模型对象 
 10  
 11   protected   $model  =  null  ;
  12  
 13   //  跳转对象 
 14  
 15   protected   $redirect  =  null  ;
  16  
 17   protected   function   __construct() {
  18  
 19              $this ->tpl = TPL:: getInstance();
  20  
 21              $this ->model = Factory:: setModel();
  22  
 23              $this ->redirect = Redirect::getInstance( $this -> tpl);
  24  
 25   }       
  26  
 27   public   function   run() {
  28  
 29              $m  =  isset ( $_GET ['m']) ?  $_GET ['m'] : 'index' ;
  30  
 31              method_exists ( $this ,  $m ) ?  $this -> $m () :  $this -> index();
  32  
 33   }
  34  
 35  }

在实例化ManageAction时,由于与此相对应的Model和其他所需Model如这里LevelModel,同样会通过Factory工厂类进行实例化(因为实例化Model放在了ManageAction的__construct()中)。

ManageAction.class.php代码如下:

  1   //  管理员控制器 
  2  
  3   class  ManageAction  extends   Action {
   4  
  5            //  等级对象 
  6  
  7            private   $level  =  null  ;
   8  
  9          
 10  
 11            public   function   __construct() {
  12  
 13                     parent:: __construct();
  14  
 15                      $this ->level =  new   LevelModel();
  16  
 17            }       
  18  
 19            public   function   add() {
  20  
 21                      if  ( isset ( $_POST ['send']))  $this ->model->add() ?  $this ->redirect->succ('?a=manage', '恭喜您,管理员添加成功!') :  $this ->redirect->error('对不起,管理员添加失败!' );
  22  
 23                      $this ->tpl->assign('allLevel', Tool::setFormItem( $this ->level->findAll(), 'id', 'level_name' ));
  24  
 25                      $this ->tpl->display(SMARTY_ADMIN.'manage/add.tpl' );
  26  
 27            }
  28  
 29  }

A. 此时在add()方法中,就直接调用了levelModel的findAll()方法即取出所有等级(新增管理员时需要),而且把返回的等级信息通过TPL对象的assign注入到模板中去,最后加载模板显示。

B. 用户点击新增管理员后,调用的是ManageModel的add()方法;

代码如下:

 1   if  ( isset ( $_POST ['send']))  $this ->model->add() ?  $this ->redirect->succ('?a=manage', '恭喜您,管理员添加成功!') :  $this ->redirect->error('对不起,管理员添加失败!');

在实例化ManageModel中,进行了许多操作,如:获取db的实例对象、Request请求处理类对象、ManageCheck验证类对象、表字段罗列、数据表名字、请求数据等;

Model.class.php代码如下:

  1   class  Model  extends   DB {
   2  
  3            //  数据库类实例 
  4  
  5            protected   $db  =  null  ;
   6  
  7            //  数据表字段 
  8  
  9            protected   $fields  =  array  ();
  10  
 11            //  数据表 
 12  
 13            protected   $tables  =  array  ();
  14  
 15            //  验证对象 
 16  
 17            protected   $check  =  null  ;
  18  
 19            //  limit 
 20  
 21            protected   $limit  = '' ;
  22  
 23            //  请求数据 
 24  
 25            protected   $_R  =  array  ();
  26  
 27          
 28  
 29            protected   function   __construct() {
  30  
 31                      $this ->db = DB:: getInstance();
  32  
 33            }
  34  
 35          
 36  
 37            //  获取request对象 
 38  
 39            protected   function   getRequest() {
  40  
 41                      return  Request::getInstance( $this ,  $this -> check);
  42  
 43            }
  44  
 45          
 46  
 47            //  新增数据 
 48  
 49            protected   function  add( Array   $postData  ) {
  50  
 51                      return   $this ->db->add( $this ->tables,  $postData  );
  52  
 53            }
  54  
 55  }

ManageModel.class.php代码如下:

  1   //  控制器模型类 
  2  
  3   class  ManageModel  extends   Model {
   4  
  5            public   function   __construct() {
   6  
  7                     parent:: __construct();
   8  
  9                      $this ->fields =  array ('id', 'user', 'pass', 'level', 'login_count', 'last_ip', 'last_time', 'reg_time' );
  10  
 11                       $this ->tables =  array (DB_PREFIX.'manage' );
  12  
 13                       $this ->check =  new   ManageCheck();
  14  
 15                       list  (
  16  
 17                                       $this ->_R['id'],
 18  
 19                                       $this ->_R['user'],
 20  
 21                                       $this ->_R['pass'],
 22  
 23                                       $this ->_R['code' ]
  24  
 25                      ) =  $this ->getRequest()->getParams( array  (
  26  
 27                                       isset ( $_GET ['id']) ?  $_GET ['id'] :  null ,
 28  
 29                                       isset ( $_POST ['user']) ?  $_POST ['user'] :  null ,
 30  
 31                                       isset ( $_POST ['pass']) ?  $_POST ['pass'] :  null ,
 32  
 33                                       isset ( $_POST ['code']) ?  $_POST ['code'] :  null 
 34  
 35                       ));
  36  
 37            }
  38  
 39          
 40  
 41            public   function   add() {
  42  
 43                      $where  =  array ("user='{ $this ->_R['user']}'" );
  44  
 45                      if  (! $this ->check->checkAdd( $this ,  $where ))  $this ->check-> error();
  46  
 47                      $requestData  =  $this ->getRequest()->filter( $this -> fields);
  48  
 49                      $requestData ['pass'] =  sha1 ( $requestData ['pass' ]);
  50  
 51                      $requestData ['last_ip'] = Tool:: getIP();
  52  
 53                      $requestData ['reg_time'] = Tool:: getDate  ();
  54  
 55                      return  parent::add( $requestData  );
  56  
 57            }
  58  
 59  }

在执行model层的add()方法时,如上,首先使用验证层对所提交数据,进行验证,验证失败,跳转到报错页面,否则继续往下执行。其验证过程封装到ManageCheck.class.php类中;

Check.class.php代码如下:

  1   class  Check  extends   Validate {
   2  
  3            //  验证结果状态 
  4  
  5            protected   $flag  =  true  ;
   6  
  7            //  错误信息集 
  8  
  9            protected   $message  =  array  ();
  10  
 11            //  模板对象 
 12  
 13            private   $_tpl  =  null  ;
  14  
 15   
 16  
 17            public   function   __construct() {
  18  
 19                      $this ->_tpl = TPL:: getInstance();
  20  
 21            }
  22  
 23            //  显示错误信息并返回 
 24  
 25            public   function  error( $url  = '' ) {
  26  
 27                      if  ( empty ( $url  )) {
  28  
 29                               $this ->_tpl->assign('message',  $this -> message);
  30  
 31                               $this ->_tpl->assign('prev', Tool:: getPrevPage());
  32  
 33                               $this ->_tpl->display(SMARTY_ADMIN.'public/error.tpl' );
  34  
 35                               exit  ;
  36  
 37                     }  else   {
  38  
 39                              Redirect::getInstance()->succ( $url  );
  40  
 41                      }
  42  
 43            }
  44  
 45  }

ManageCheck.class.php代码如下:

  1   //  管理员验证类 
  2  
  3   class  ManageCheck  extends   Check {
   4  
  5            //  验证新增数据 
  6  
  7            public   function  checkAdd(Model & $model ,  Array   $params  ) {
   8  
  9                      if  (self::isNullString( $_POST ['user' ])) {
  10  
 11                               $this ->message[] = '管理员用户名不得为空!' ;
  12  
 13                               $this ->flag =  false  ;
  14  
 15                      }
  16  
 17                      if  (!self::checkStrLength( $_POST ['user'], 2, 'min' )) {
  18  
 19                               $this ->message[] = '管理员用户名不得小于2位!' ;
  20  
 21                               $this ->flag =  false  ;
  22  
 23                      }
  24  
 25                      if  (!self::checkStrLength( $_POST ['user'], 20, 'max' )) {
  26  
 27                               $this ->message[] = '管理员用户名不得大于20位!' ;
  28  
 29                               $this ->flag =  false  ;
  30  
 31                      }
  32  
 33                      if  (!self::checkStrLength( $_POST ['pass'], 6, 'min' )) {
  34  
 35                               $this ->message[] = '管理员密码不得小于6位!' ;
  36  
 37                               $this ->flag =  false  ;
  38  
 39                      }
  40  
 41                      if  (!self::checkStrEqual( $_POST ['pass'],  $_POST ['notpass' ])) {
  42  
 43                               $this ->message[] = '确认密码与密码必须保持一致!' ;
  44  
 45                               $this ->flag =  false  ;
  46  
 47                      }
  48  
 49                      if  (self::isNullString( $_POST ['level' ])) {
  50  
 51                               $this ->message[] = '必须选择管理员等级权限!' ;
  52  
 53                               $this ->flag =  false  ;
  54  
 55                      }
  56  
 57                      if  ( $model ->checkOne( $params  )) {
  58  
 59                               $this ->message[] = '管理员用户名已被占用!' ;
  60  
 61                               $this ->flag =  false  ;
  62  
 63                      }
  64  
 65                      return   $this -> flag;
  66  
 67            }
  68  
 69  }

然后使用Request请求处理类,对提交数据,进行入库前的过滤

代码如下:

 1   $requestData  =  $this ->getRequest()->filter( $this ->fields);

最后,填充数据库应有字段,如时间,用户ip,密码加密等

代码如下:

 1   $requestData ['pass'] =  sha1 ( $requestData ['pass' ]);
  2  
 3   $requestData ['last_ip'] = Tool:: getIP();
  4  
 5   $requestData ['reg_time'] = Tool:: getDate ();

然后通过父类调用DB对象中的add()方法,新增一条数据;

代码如下:

  1   return  parent::add( $requestData  );
   2  
  3   
  4  
  5                     //  新增数据 
  6  
  7                     protected   function  add( Array   $postData  ) {
   8  
  9                               return   $this ->db->add( $this ->tables,  $postData  );
  10  
 11                    }

DB.class.php关键代码如下:

  1   //  新增 
  2  
  3            protected   function  add( $tables ,  Array   $postData  ) {
   4  
  5                      $addFields  =  array  ();
   6  
  7                      $addData  =  array  ();
   8  
  9                      foreach  ( $postData   as   $key => $value  ) {
  10  
 11                               $addFields [] =  $key  ;
  12  
 13                               $addData [] =  $value  ;
  14  
 15                      }
  16  
 17                      $addFields  =  implode (',',  $addFields  );
  18  
 19                      $addData  =  implode ("','",  $addData  );
  20  
 21                      $sql  = "INSERT INTO  $tables [0] ( $addFields ) VALUES (' $addData ')" ;
  22  
 23                      return   $this ->execute( $sql )-> rowCount();              
  24  
 25           }

最后把是否新增成功的数据的结果,逐层从DB->Model->ManageModel->Controller反馈到ManageAtion的add方法中,如果新增成功跳转到成功提示页面,如果失败跳转到失败提示页面;

代码如下:

 1   if  ( isset ( $_POST ['send']))  $this ->model->add() ?  $this ->redirect->succ('?a=manage', '恭喜您,管理员添加成功!') :  $this ->redirect->error('对不起,管理员添加失败!');

到此,整个执行流程执行完毕!

小结:整个执行流程按照非常严格的MVC的设计思想在进行,每一个层次的职责都非常明确。如controller控制器层,专门负责逻辑判断,页面跳转等,是一个调度者。它可以调度model层去获取数据,验证数据、填充数据等,它还可以调度view层,把数据给显示出来。

最后,整个框架的分析到这里就结束,接下来会对其中的重要模块或功能进行总结。

学而时习之,不亦说乎?有朋自远方来,不亦乐乎?*\(^v^)/*

 

分类:  php与mysql

标签:  李炎恢 ,  第三季 ,  php ,  在线商城 ,  总结 ,  mvc

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于在线商城表结构的详细内容...

  阅读:43次