前阵子碰上一个关于产品多属性搜索的问题,给实现了,现在拿出来跟大家探讨探讨,有什么好建议记得留下。
首先说明下,下面的实现,都仅仅是简易版,纯属抛砖引玉而为,更强大的功能只能做相应的额外扩展才行。
本文略过分类、属性、产品的创建过程的源码解析,如下仅附上图片说明。
图一:创建分类(仅两级)
图二:创建属性
图三:创建产品(这里属性是可多选的)
下面直奔产品多属性搜索环节。
首先说明一下,本文所用的搜索程序首次加载会将库中所有的产品显示出来,然后通过搜索结果,隐藏掉不匹配的产品,显示正确的产品,从而实现搜索效果。
下面是整个搜索过程的图片展示。
图四:搜索首次加载结果
图五:父分类搜索(含子分类数据)
图六:子分类搜索
图七:分类+多属性搜索(1)
图八:分类+多属性搜索(2)
图九:分类+多属性搜索(3)
图十:分类+多属性搜索(4)
图十一:分类+多属性搜索(5)
图十二:分类+多属性搜索(6)
图十三:分类+多属性搜索(7)
搜索程序前台源码(displayProduct.php):
View Code
1 4 5 6 7产品展示搜索 8 9 10 11 12 13 2829 3045 135 13631 产品分类 32 3334 3536 37 3839 4041 4244没有搜索到结果!43
搜索程序后台源码(displayProduct.process.php):
View Code
1 0,'msg'=>'非法查询类型!'));13 break;14 }15 exit;
搜索程序后台数据处理层(product.model.php)源码:
View Code 95 96
1 '.$pref.$row['name'].''; 18 } 19 20 $categoryList = ''; 21 return $categoryList; 22 } 23 24 public static function getAttributeList($search=false){ 25 global $db; 26 $sql = "SELECT id,name,0 AS ordering,id AS 'groupcol' FROM `ju_attributes` WHERE parent=0 27 UNION 28 SELECT id,name,ordering,parent AS 'groupcol' FROM `ju_attributes` 29 WHERE parent IN( 30 SELECT id FROM `ju_attributes` WHERE parent=0 31 ) ORDER BY `groupcol`,`ordering`"; 32 $result = mysql_query($sql,$db); 33 $attributeList = ''; 34 if($search){ 35 while($row = mysql_fetch_assoc($result)){ 36 if($row['id'] == $row['groupcol']) { 37 $attributeList .= '
- '.$row['name'].' '; 38 }else { 39 $attributeList .= '
- '.$row['name'].' '; 40 } 41 } 42 if(stripos($attributeList,'
%s
97 98 ¥%.2f 99 ¥%.2f100
101 102 TPL;103 $sql = "SELECT id,name,price,origPrice FROM `ju_products` ORDER BY id";104 $result = mysql_query($sql,$db);105 $productList = '';106 while($row = mysql_fetch_assoc($result)){107 $productList .= vsprintf($productTpl,array($row['id'],'#',$row['name'],$row['name'],$row['price'],$row['origPrice']));108 }109 return $productList;110 }111 112 public static function searchProductByCategory($catid){113 global $db;114 if(!isset($catid)) return array('status'=>0,'msg'=>'分类不能为空!');115 116 $categories = self::getSubCategories($catid); //默认递归包含子分类117 $sql = "SELECT id FROM `ju_products` WHERE catid IN(".implode(',',$categories).") ORDER BY id";118 $result = mysql_query($sql,$db);119 $productArray = array();120 while($row = mysql_fetch_assoc($result)){121 array_push($productArray,$row['id']);122 }123 return array('status'=>1,'products'=>$productArray);124 }125 public static function searchProductByAttribute($searchString,$catid=0){126 global $db;127 if(empty($searchString)) return array('status'=>0,'msg'=>'搜索条件不能为空!');128 129 if(empty($catid)) $where = array();130 else $where = array("p.catid IN(".implode(',',self::getSubCategories((int)$catid)).")");131 $ands = explode('|',$searchString);132 foreach($ands as $and){133 $andString = "";134 $ors = explode(',',$and);135 foreach($ors as $or){136 $andString .= "LOCATE(',{ $or},',pas.attribute_ids) OR ";137 }138 $andString = '('.substr($andString,0,strlen($andString)-4).')'; //-4去掉末尾“ OR ”139 $where[] = $andString;140 }141 142 $sql = "143 SELECT p.id FROM `ju_products` as p144 INNER JOIN (145 SELECT product_id,concat(',,',group_concat(attribute_id),',,') as attribute_ids FROM `ju_product_attributes` GROUP BY product_id146 ) as pas ON p.id=pas.product_id147 WHERE ".implode(' AND ',$where)."148 group by p.id149 ";150 $result = mysql_query($sql,$db);151 $productArray = array();152 while($row = mysql_fetch_assoc($result)){153 array_push($productArray,$row['id']);154 }155 return array('status'=>1,'products'=>$productArray,'sql'=>$sql);156 }157 158 public static function getSubCategories($pid,$recursive=true){159 global $db;160 $pid = (int)$pid;161 $sql = "SELECT id FROM `ju_categories` as cate WHERE cate.parent=".$pid;162 $result = mysql_query($sql,$db);163 $subCategories = array($pid); //加入当前分类164 if($recursive){165 while($row = mysql_fetch_row($result)){166 $subCategories = array_merge($subCategories,self::getSubCategories($row[0]));167 }168 }169 return $subCategories;170 }171 }172 173 //End_php 数据库连接文件(db.php)源码:
View Code
1
重点:多属性搜索方法
1 public static function searchProductByAttribute($searchString,$catid=0){ 2 global $db; 3 if(empty($searchString)) return array('status'=>0,'msg'=>'搜索条件不能为空!'); 4 5 if(empty($catid)) $where = array(); 6 else $where = array("p.catid IN(".implode(',',self::getSubCategories((int)$catid)).")"); //WHERE子句数组,分类搜索(getSubCategories方法默认含子分类) 7 $ands = explode('|',$searchString); //分离不同层级的属性,如品牌与价格范围 8 foreach($ands as $and){ 9 $andString = "";10 $ors = explode(',',$and); //分离同一层级的多个属性,如品牌中的"HP","华硕","联想"等11 foreach($ors as $or){12 $andString .= "LOCATE(',{ $or},',pas.attribute_ids) OR "; //对每个属性进行LOCATE定位,定位目标为各个产品所有属性组成的属性串,格式为:,,26,33,3,21,,13 }14 $andString = '('.substr($andString,0,strlen($andString)-4).')'; //-4去掉末尾“ OR ”15 $where[] = $andString; //加入WHERE子句数组中16 }17 //使用group_concat(attribute_id)拼接每个产品的所有属性,用于WHERE子句进行属性LOCATE搜索18 $sql = "19 SELECT p.id FROM `ju_products` as p20 INNER JOIN (21 SELECT product_id,concat(',,',group_concat(attribute_id),',,') as attribute_ids FROM `ju_product_attributes` GROUP BY product_id22 ) as pas ON p.id=pas.product_id23 WHERE ".implode(' AND ',$where)." //使用AND拼接WHERE子句数组24 group by p.id25 ";26 $result = mysql_query($sql,$db);27 $productArray = array();28 while($row = mysql_fetch_assoc($result)){29 array_push($productArray,$row['id']); //将查得产品id加入$productArray数组中,响应请求。30 }31 return array('status'=>1,'products'=>$productArray,'sql'=>$sql);32 }
本文到此结束,谢谢大家耐心阅读!
附: