深入PHP购物车模块功能分析(函数讲解,附源码)


Posted in PHP onJune 25, 2013

一,购物车概述
购物车是为消费者在网上购物中提供一个临时存储商品的地方。其主要功能包括:添加商品、删除商品、更改商品数量、商品金额小计、商品金额总计和清空购物车;还包括生成订单、订单打印、订单预览、提交订单和取消购物等。
购物车的操作流程:首先,登录到网站中浏览商品;然后,购买指定的商品,进入购物车页面中,在该页面可以实现更改商品数量、删除商品、清空购物车、继续购物等;最后,填写收货人信息,生成订单,订单打印、预览,提交订单等操作。

二,热点关键技术
1,Smarty模块的安装配置
smarty是一个使用PHP写出来的PHP模板引擎,它将一个应用程序分成两部分实现:视图和逻辑控制。即将UI和PHP代码分离。PHP没有内置Smarty模板类,需要单独下载和配置,而且Smarty要求服务器上PHP版本最低为4.0.6。PHP Smarty可以在http://www.smarty.net/download下载。将压缩包解压,其中有一个libs目录,包含Smarty类库的所有核心文件。包括smarty.class.php、smarty_Compiler.class.php、config_File.class.php和debug.tpl 4个文件,还有internals和plug-ins两个目录。
复制libs目录到服务器根目录下,并重命名。这里将libs目录重新命名为smarty。到此Smarty模板安装完毕。
2,Smarty模板的配置
(1)首先确定Smarty目录的位置。因为Smarty类库是通用的,每一个项目基本都会使用,为了调用方便,习惯将smarty放置在根目录下。

(2)新建4个目录templates、templates_c、configs和cache,用于存储不同的文件。新建的4个目录位置是可以选择的,只要配置文件路径设置正确就可以了。

(3)创建配置文件。只要应用Smarty模板,那么就一定要包含Smarty类库和相关信息。每个页面都写一遍配置是不现实的,最好的方法就是将这些配置信息都写到一个文件中,通过include来调用配置文件。配置文件创建完成后保存在根目录下。本模块配置文件config.php代码如下:

<?php
 /*  定义服务器的绝对路径  */
 define('BASE_PATH','E:\PHPservices\\');
 /*  定义Smarty目录的绝地你路径  */
 define('SMARTY_PATH','SourceCode\12\01\\');
 /*  加载Smarty类库文件  */
 require BASE_PATH.SMARTY_PATH.'smarty\Smarty.class.php';
 /*  实例化一个Smarty对象  */
 $smarty = new Smarty;
 /*  定义各个目录的路径 */
 $smarty->template_dir = BASE_PATH.SMARTY_PATH.'./';
 $smarty->compile_dir = BASE_PATH.SMARTY_PATH.'templates_c/';
 $smarty->config_dir = BASE_PATH.SMARTY_PATH.'configs/';
 $smarty->cache_dir = BASE_PATH.SMARTY_PATH.'cache/';
 /*  定义定界符  */
 $smarty->left_delimiter = '<{';
 $smarty->right_delimiter = '}>';
 /*  使用Smarty赋值方法将一对儿名称/方法发送到模板中  */
?>

3,smarty模板动静分离
smarty模板最大的特点就是实现应用程序的动静分离,即将UI和PHP代码分离。下面介绍Smarty模板在实现动静分离的过程中常用的技术。
(1)在UI中获取PHP代码中模板变量的值
首先要确定Smarty模板的界定符,这里使用的是'<{'和'}>'。另外还应用到一些Smarty的内建函数section、php、if、elseif、else等。
a)section函数用于遍历数组中的数据。每个{section}标签必须与闭合标签{/section}成对出现,参数name和loop为必选项。
名称name是包含字母、数字和下划线的任意组合,可以嵌套但必须保证嵌套的name唯一。
变量loop(通常是数组)决定循环执行的次数,例如需要在section循环内输出变量时,必须在变量后加上中括号,中括号内包含name变量。
例如:
<{section name=data  loop=$myrow }>
 <tr>
  <td width="125" bgcolor="#FFFFFF"><{$myrow[data].tb_commodity_name}></td>
  <td bgcolor="#FFFFFF"><{$myrow[data].tb_commodity_price}></td>
 </tr>
<{/section}>b)php标签的作用是直接在模板中嵌入PHP脚本,标签的格式是"<{php}>"和"<{/php}>".
c)在Smarty的模板中同样也支持if、else语句,而且还增加了几个特性以适应模板引擎。if与/if必须成对出现;可以使用else和elseif字句;可使用以下条件修饰词:eq、ne、neq、gt、lt、lte、le、gte、ge、is even、is odd、is not even、is not odd、not、mod、div by、even by、odd by、===、!=、>、<、<=、>=。在使用修饰词时必须和变量或者常量用空格分隔开来。示例如下:
<{if $isShow=="F" }>
 <tr>
        <td height="22" colspan="5" bgcolor="#FFFFFF"><div align="center">对不起,您的购物车中暂无商品信息!</div></td>
    </tr>
<{else}>
 <{section name=data loop=$myrow }>
  <tr>
   <td height="22" align="center" bgcolor="#FFFFFF"><{$myrow[data].tb_commodity_name}></td>
   <td height="22" bgcolor="#FFFFFF"><div align="center"><{$myrow[data].tb_commodity_price}></div></td>
  </tr>
 <{/section}>
<{/if}>

(2)在PHP代码中定义模板变量,为模板变量赋值
UI中的数据是来自于PHP代码中定义的模板变量。在PHP代码中,完成PHP代码的编写,将要输出的值赋给一个模板变量,最后制定模板页进行输出。
a)为模板变量赋值通过自定义函数assign()来完成,其中第一个参数是被赋值的变量名,第二个参数是赋给变量的值。应用assign()函数的关键代码如下:
$smarty->assign("myrow",$array); //通过assign方法将数组$array中的数据写入到myrow中b)模板页的指定是通过display方法来完成的,其语法如下:
void display(string template[,string cache_id[,string compile_id]])
该方法用于指定模板页,其中第一个必选参数是指定一个合法模板资源的类型和路径;第2个可选参数指定一个缓存号;第3个可选参数指定一个编译号,再把一个模板编译成不同版本时使用。display方法应用的关键代码如下:
$smarty->display("index.tpl"); //指定要输出的模板页3,Session购物车的创建
Session购物车主要应用Session变量来实现。而所谓的购物车就是通过session_register()函数创建的2个Session变量;其中goodsid存储商品的ID,goodsnum存储商品的数量。Session购物车创建的代码如下:
<?php 
 session_start();  //初始化session变量
 session_register("goodsid"); //定义session变量用于存储商品ID
 session_register("goodsnum"); //定义session变量用于存储购买商品的数量
?>

session_register()函数,在整个域范围内增加一个Session变量。语法:boolean session_register(string name);
参数name用于指定新Session变量的名称。
4,通过数组函数判断购物车是否存在指定商品
为了避免在购物车中出现商品的重复添加,要对添加的商品与购物车中存储的商品进行判断。
a)应用explode()函数,将goodsid变量中存储的字符串以@为分隔符转换到数组中。
explode()函数,返回由字符串组成的数组,其中的每个元素都是由separator作为边界点分割出来的子字符串。
语法:array explode(string separator,string string,[ing limit])
参数说明:
separator:必须,规定在哪里分割字符串。不能为空字符串,否则explode()返回FALSE
string:必须,要分割的字符串。limit:可选,规定所返回的数组元素的最大数目。如果设置了limit参数,则返回的数组包含最多limit个元素,而最后那个元素将包含string的剩余部分。如果limit参数是负数,则返回除了最后的-limit个元素之外的所有元素。

b)in_array()函数判断数组中是否存在指定的商品ID,如果存在,则说明商品已经在购物车中;否则商品不存在,则将商品的ID添加到购物车中。

in_inarray()函数在数组中搜索给定的值。如果找到则返回True,否则返回False。
语法:bool in_array(mixed value,array array[,bool type])
参数说明:
value:必须,规定要在数组中搜索的值
array:必须,规定要搜索的数组。
type:可选,如果设置为true,则检查搜索的数据与数组的类型是否相同。
在购物车模块中,判断购物车中是否存在指定的商品的代码如下:

<?php 
 session_start(); //初始化session变量
 session_register("goodsid"); //定义session变量用于存储商品ID
 session_register("goodsnum"); //定义session变量用于存储购买商品的数量
 if($_SESSION["goodsid"]=="" && $_SESSION["goodsnum"]==""){ //判断session变量是否为空
  $_SESSION["goodsid"]=$_GET["id"]."@"; //如果session变量为空,则为其赋值为商品的ID,并以@分隔
  $_SESSION["goodsnum"]="1@";  //如果session变量为空,则为其赋值为1,并以@分隔
 }else{ //如果session变量不为空
   $array=explode("@",$_SESSION["goodsid"]); //则以@为分隔符,将session变量中的数据写入到数组中
   if(in_array($_GET["id"],$array)){ //如果判读数组中是否存在指定的ID
     echo "<script>alert('该商品已经被放入购物车!');history.back();</script>";
     exit;
   }
  //如果数组中不存在指定的ID,则说明该商品还没有放入购物车中
  $_SESSION["goodsid"].=$_GET["id"]."@"; //将该商品添加到购物车中
  $_SESSION["goodsnum"].="1@"; //更改商品数量
 }
 echo "<script>window.location.href='shopping_car.php';</script>";
?>

5,验证输入商品数量值是否有效
在preg_match()函数中,判断提交的商品数量的值是否符合正则表达式的标准,如果符合则有效,否则将给出提示信息。程序关键代码如下:
$id=$_POST["id"];       //获取商品id
$num=$_POST["goodsnum"];     //获取商品数量
$preg="/^[0-9]*[0-9]$|^[0-9]*[0-9]$/";  //编写正则表达式
if($num==""){        //判断提交的值是否为空
 echo "<script>alert('数量不能为空!');history.back();</script>";
 exit;
}else if(!preg_match($preg,$num,$str)){  //判断提交的数据是否是正整数
  echo "<script>alert('数量只能为正整数!');history.back();</script>";
  exit;
}

preg_match()函数,在字符串中搜索所有与给出的正则表达式匹配的内容,如果存在则返回True,否则返回False。语法如下:
语法:int preg_match(string pattern,string sbuject[,array matches[,int flags]])
参数说明:
pattern:必要参数,需要匹配的正则表达式
subject:必要参数,输入的字符串matches:可选参数。输出的搜索结果的数组,例如$out[0]将包含与整个模式匹配的结果,$out[1]将包含与第一个捕获的括号中的子模式所匹配的结果,一次类推
flags:可选参数,标记:PREG_OFFSET_CAPTURE,对每个出现的匹配结果页同时返回共附属的字符串偏移量

三,函数实现过程
1,添加商品功能
添加商品功能的实现原理是:首先创建一个购物车,然后以商品展示页中“购买”链接传递的商品ID($_GET[id])为依据,向购物车中添加商品(商品ID),并且不允许重复添加。向购物车中添加商品的操作通过by_commodity.php文件来完成。
首先,创建一个购物车。
然后,判断购物车中是否为空,如果为空,则将商品的ID和数量添加到购物车中;如果不为空,则要判断添加商品的ID是否在购物车中已经存在,如果存在则不能重复添加,否则将商品ID添加到购物车中。
添加商品程序代码如下:

<?php
 header("Content-type:text/html;charset= utf-8");
 session_start();  //初始化session变量
 session_register("goodsid"); //定义session变量用于存储商品ID
 session_register("goodsnum"); //定义session变量用于存储购买商品的数量
 if($_SESSION["goodsid"]=="" && $_SESSION["goodsnum"]==""){  //判断session变量是否为空
  $_SESSION["goodsid"]=$_GET["id"]."@";      //如果session变量为空,则为其赋值为商品的ID,并以@分隔
  $_SESSION["goodsnum"]="1@";      //如果session变量为空,则为其赋值为1,并以@分隔
 }else{            //如果session变量不为空
   $array=explode("@",$_SESSION["goodsid"]);  //则以@为分隔符,将session变量中的数据写入到数组中
   if(in_array($_GET["id"],$array)){    //如果判读数组中是否存在指定的ID
     echo "<script>alert('该商品已经被放入购物车!');history.back();</script>";
     exit;
   }
  //如果数组中不存在指定的ID,则说明该商品还没有放入购物车中
  $_SESSION["goodsid"].=$_GET["id"]."@";   //将该商品添加到购物车中
  $_SESSION["goodsnum"].="1@";     //更改商品数量
 }
 echo "<script>window.location.href='shopping_car.php';</script>";
?>

2,删除购物车中商品功能的实现
删除购物车中商品的操作是根据“删除该项”超级链接中传递的商品ID($_GET[id])执行的。在delete_commodity.php文件中,根据$_GET[id]传递的值,执行删除购物车中商品的操作。
首先,获取$_GET[id]传递的值。然后,应用explode()函数,将Session变量中存储的商品ID和数量的数据写入数组,并以@作为分隔符。
接着,应用array_search()函数,获取数组中指定ID商品的键名,并根据获取的键名将数组中指定的数据赋值为空。
最后,将数组中重新赋值的空数据写入购物车中,从而完成删除购物车中指定商品的操作。
<?php
 session_start();    //初始化session变量
 require("config.php");   //连接smarty模板
 $id=$_GET["id"];    //获取要删除商品的ID
 $arrayid=explode("@",$_SESSION["goodsid"]);  //将购物车中存储的商品ID的字符串转换到数组中
 $arraynum=explode("@",$_SESSION["goodsnum"]); //将购物车中存储的商品数量的字符串转换到数组中
 $key=array_search($id,$arrayid);    //获取到数组中指定的数据,并返回键名
 $arrayid[$key]="";        //根据返回的键名,将数组中的数据赋值为空
 $arraynum[$key]="";        //根据返回的键名,将数组中的数据赋值为空
 $_SESSION["goodsid"]=implode("@",$arrayid);  //重新将数组中的数据添加到购物车中
 $_SESSION["goodsnum"]=implode("@",$arraynum); //重新将数组中的数据添加到购物车中
 echo "<script>window.location.href='shopping_car.php';</script>";
 $smarty->display("shopping_car.tpl");
?>

删除前$_SESSION["goodsid"]的值为"3@2@5@",删除$id=5后$_SESSION["goodsid"]的值为"3@2@@";这样Session中存在多余的数据@。
解决方法:
<?php
 session_register("goods"); //创建session数组
 $id=$_GET['id'];
 $arraygoods=$_SESSION["goods"];
 if($_SESSION["goods"]==""){
  $_SESSION["goods"][$id]="$id,1"; //根据商品ID保存商品,键名为$id,键值为$id,1(商品ID和购买商品数量,默认购买数量为1)
 }else{
  if(array_key_exists($id,$_SESSION["goods"])){
    echo "<script>alert('该商品已经被放入购物车!');history.back();</script>";
    exit;
  }
  $_SESSION["goods"][$id]="$id,1";
 }
?>

商品信息以数组形式保存,[4] => 4,4。键名为商品ID,值为键名和购买商品数量。添加删除商品只需要根据ID号找到对应商品修改信息即可。
Array
(
    [4] => 4,4
    [3] => 3,5
    [1] => 1,10
    [2] => 2,1
)

3,生成订单功能的实现
生成订单功能就是从数据库中读取出填写的订单信息,对其内容进行重新整合,形成一个订单模式,并且实现订单打印和订单预览的功能。订单生成的操作通过两个文件来完成,一个是从数据库中读取数据,将所需的数据赋值给指定的Smarty模板变量,并指定模板页。
<?php 
 session_start();
 header("Content-type:text/html;charset= utf-8");
 require_once("conn.php");
 require_once("config.php");
 $array=array();        //定义一个空数组
 $ddnumber=base64_decode($_GET["ddno"]);
 mysql_query("set names utf8");
 $sql=mysql_query("select * from tb_commodity_order_form where ddnumber='".$ddnumber."'",$conn);
 $info=mysql_fetch_array($sql);
 array_push($array,$info);    //将获取的数组值写入到新的数组中
 $smarty->assign("info",$array);
 $array=explode("@",$info["spc"]);
 $arraynum=explode("@",$info["slc"]);
 $totalprice=0;         //定义价格变量
 $arrayinfo=array();        //创建数组
 for($i=0;$i<count($array);$i++){
  if($array[$i]!=""){
   $sqlcart=mysql_query("select * from tb_commodity where tb_commodity_id='".$array[$i]."'",$conn);
   $infocart=mysql_fetch_array($sqlcart); //读取数据库中数据
   $totalprices=$infocart["tb_commodity_price"]*$arraynum["$i"];  //计算总的价格
   array_push($infocart,$arraynum["$i"]);  //将购买数量的数据写入到数据库中返回的数组中    
   array_push($infocart,$totalprices);  //将购买数量的数据写入到数据库中返回的数组中    
   array_push($arrayinfo,$infocart);       //将整理的数据压入到创建的新数组中
   $totalprice+=$infocart["tb_commodity_price"]*$arraynum["$i"];  //计算总的价格
  }
 }
 session_unregister("goods");
 if(count($arrayinfo)>0){      //判断数组是否为空
  $gnum=count($arrayinfo);
  $smarty->assign("isShow","T");
  $smarty->assign("gnum",$gnum);
  $smarty->assign("myrow",$arrayinfo);
  $smarty->assign("totalprice",$totalprice);
 }else{
  $smarty->assign("isShow","F");
 }
 $smarty->display("shopping_dd.tpl");
?>

另一个是shopping_dd.tpl模板页,输出模板变量中存储的数据,生成一个订单。

四,源代码下载:点击下载

PHP 相关文章推荐
让PHP支持断点续传的源码
May 16 PHP
PHP XML数据解析代码
May 26 PHP
PHP安全技术之 实现php基本安全
Sep 04 PHP
让PHP以ROOT权限执行系统命令的方法
Feb 10 PHP
div li的多行多列 无刷新分页示例代码
Oct 16 PHP
PHP中鲜为人知的10个函数
Feb 28 PHP
php中smarty实现多模版网站的方法
Jun 11 PHP
ThinkPHP函数详解之M方法和R方法
Sep 10 PHP
Yii中实现处理前后台登录的新方法
Dec 28 PHP
Laravel学习教程之request validation的编写
Oct 25 PHP
PHP使用pdo实现事务处理操作示例
Sep 05 PHP
laravel ajax curd 搜索登录判断功能的实现
Apr 17 PHP
基于PHP+Ajax实现表单验证的详解
Jun 25 #PHP
PHP Class&amp;Object -- 解析PHP实现二叉树
Jun 25 #PHP
PHP Class&amp;Object -- PHP 自排序二叉树的深入解析
Jun 25 #PHP
通过PHP current函数获取未知字符键名数组第一个元素的值
Jun 24 #PHP
PHP多例模式介绍
Jun 24 #PHP
PHP获取和操作配置文件php.ini的几个函数介绍
Jun 24 #PHP
PHP垃圾回收机制引用计数器概念分析
Jun 24 #PHP
You might like
php数组函数序列之next() - 移动数组内部指针到下一个元素的位置,并返回该元素值
2011/10/31 PHP
php去除换行符的方法小结(PHP_EOL变量的使用)
2013/02/16 PHP
在html文件中也可以执行php语句的方法
2015/04/09 PHP
PHPWind9.0手动屏蔽验证码解决后台关闭验证码但是依然显示的问题
2016/08/12 PHP
php使用mysqli和pdo扩展,测试对比mysql数据库的执行效率完整示例
2019/05/09 PHP
PHP使用PDO创建MySQL数据库、表及插入多条数据操作示例
2019/05/30 PHP
Aster vs Newbee BO5 第一场2.19
2021/03/10 DOTA
在线游戏大家来找茬II
2006/09/30 Javascript
通过修改referer下载文件的方法
2008/05/11 Javascript
让任务管理器中的CPU跳舞的js代码
2008/11/01 Javascript
javascript+iframe 实现无刷新载入整页的代码
2010/03/17 Javascript
js弹出层之1:JQuery.Boxy (二)
2011/10/06 Javascript
js中点击空白区域时文本框与隐藏层的显示与影藏问题
2013/08/26 Javascript
Angular指令之restict匹配模式的详解
2017/07/27 Javascript
基于JavaScript实现飘落星星特效
2017/08/10 Javascript
Vue.js 2.0和Cordova开发webApp环境搭建方法
2018/02/26 Javascript
详解js模板引擎art template数组渲染的方法
2018/10/09 Javascript
服务端预渲染之Nuxt(使用篇)
2019/04/08 Javascript
vue history 模式打包部署在域名的二级目录的配置指南
2019/07/02 Javascript
使用JS监听键盘按下事件(keydown event)
2019/11/07 Javascript
[02:07]DOTA2超级联赛专访BBC:难忘网吧超神经历
2013/06/09 DOTA
python在linux中输出带颜色的文字的方法
2014/06/19 Python
Python3实现从指定路径查找文件的方法
2015/05/22 Python
详细解读Python中解析XML数据的方法
2015/10/15 Python
python队列通信:rabbitMQ的使用(实例讲解)
2017/12/22 Python
Python3使用TCP编写一个简易的文件下载器功能
2019/05/08 Python
对django layer弹窗组件的使用详解
2019/08/31 Python
pycharm无法导入本地模块的解决方式
2020/02/12 Python
CSS3模拟动画下拉菜单效果
2017/04/12 HTML / CSS
夏洛特和乔治婴儿和儿童时装精品店:Charlotte and George
2018/06/06 全球购物
ASOS西班牙官网:英国在线时尚和美容零售商
2020/01/10 全球购物
公司营业员的自我评价
2014/03/04 职场文书
商务专员岗位职责范本
2014/06/29 职场文书
2016应届大学生自荐信模板
2016/01/28 职场文书
2019暑假学生安全口号
2019/06/27 职场文书
使用CSS自定义属性实现骨架屏效果
2022/06/21 HTML / CSS