相信很多学PHP的很多小伙伴都会尝试做一个网上商城作为提升自己技术的一种途径。各种对商品分类,商品名之类的操作应该是得心应手,那么就可以尝试下无限级分类列表的制作了。
到网上一搜PHP无限极分类,很多,但好多都是一个,并且,写的很乱,代码很多,让我们怎么学习嘛,那些都不靠谱,还是自己捣鼓捣鼓无限极分类了。
什么是无限级分类?
无限级分类是一种分类技巧,例如部门组织,文章分类,学科分类等常用到无限级分类,将其简单理解成分类就好了。其实我们仔细想一下,生活中的分类简直太多了,衣服可以分为男装和女装,也可以分为上衣和裤子,也可以根据年龄段分类。分类无处不在,分类显得“无限”。我这里就不说无限分类的必要性了。
无限级分类原理简介
无限分类看似"高大上",实际上原理是非常简单的 。无限分类不仅仅需要代码的巧妙性,也要依托数据库设计的合理性。要满足无限级分类,数据库需要有两个必须的字段,id,pid。id用来标识自身,而pid则是用来表明父级id。也就是说,每个分类记录不仅描述了自身,还描述了与其关心最为紧密的另一个id。看似复杂的事情被这样一个小技巧解决了。
闲话不多说,该展现本文的实例了。
作为一个狂热海贼迷,这篇的实例我就以《海贼王》人物组织做案例。
数据库准备:
这里还是科普下海贼王里面的设定:世界分为三大阵营:海军,海贼,革命军。海军有大将:青雉,赤犬,黄猿。海贼有:四皇,七武海,草帽海贼团。四皇有香克斯,七武海有多弗朗明哥,克洛克达尔,草帽海贼团有索隆。(打个广告:海贼王真的很好看)。 代码: 我封装了一个Unlimited类,用来调用diaplayList()展现下拉列表形式,调用diaplayLink展现导航Link分类。也可以增加(addNodes())和删除(deleteNodes)分类。 private function getList($pid=0,&$result=array(),$spac=0){ } private function getLink($cid,&$result=array()){ } @param [type] $pid 父类id @param [type] $name 本类名 return true; } 类中函数主要采取了递归函数的方法,如果理解深刻理解递归函数,其余的部分也就水到渠成了。我会在后面的部分详细介绍实现递归函数的三种方法。 我们再来看一个实例: 首先建立分类信息表: 插入若干数据: //获取某个分类的所有子分类 } //获取某个分类的所有父分类 //方法二,迭代 //测试 部分 $result=getSons($categorys,1); $result=getSubs($categorys,0); $result=getParents($categorys,7); $result=getParents2($categorys,15); 看下最终结果吧
protected $mysqli;
public function __construct($config){
$this->MysqLi=new MysqLi($config['host'],$config['user'],$config['pwd']);
$this->MysqLi->select_db($config['db']);
$this->MysqLi->set_charset('utf8');
if ($this->MysqLi->connect_errno) {
echo $this->MysqLi->connect_error;
}
}
$spac=$spac+2;
$sql="select * from onepiece where pid={$pid}";
$rs=$this->MysqLi->query($sql);
while($row=$rs->fetch_assoc()) {
$row['name']=str_repeat(' ',$spac).$row['name'];
$result[]=$row;
$this->getList($row['id'],$result,$spac);
}
return $result;
}
/**
*/
public function displayList(){
$rs=$this->getList();
$str="foreach ($rs as $key => $val) {
$str.="<option >{$val['name']}</option>";
}
$str.="</select>";
return $str;
$sql="select * from onepiece where id={$cid}";
$rs=$this->MysqLi->query($sql);
if($row=$rs->fetch_assoc()){
$result[]=$row;
$this->getLink($row['pid'],$result);
}
return array_reverse($result);
}
/**
*/
public function displayLink($cid){
$rs=$this->getLink($cid);
$str='';
foreach ($rs as $val) {
$str.="{$val['name']}>";
}return $str;
/**
*/
public function addNodes($pid,$name){
$sql="insert into onepiece values('',{$pid},'".$name."')";
if($this->MysqLi->query($sql)){}
/**
/
public function deleteNodes($id){
$sql="select from onepiece where pid ={$id}";
$rs=$this->MysqLi->query($sql);
if($row=$rs->fetch_assoc()){
$mes="还有子元素,请勿删除";
}else{
$sql="delete from onepiece where id={$id}";
if($this->MysqLi->query($sql)){
$mes="删除成功";
}
}
return $mes;
}
}
function getSons($categorys,$catId=0){
$sons=array();
foreach($categorys as $item){
if($item['parentId']==$catId)
$sons[]=$item;
}
return $sons;
}
function getSubs($categorys,$catId=0,$level=1){
$subs=array();
foreach($categorys as $item){
if($item['parentId']==$catId){
$item['level']=$level;
$subs[]=$item;
$subs=array_merge($subs,getSubs($categorys,$item['categoryId'],$level+1)); }
return $subs;
}
//方法一,递归
function getParents($categorys,$catId){
$tree=array();
foreach($categorys as $item){
if($item['categoryId']==$catId){
if($item['parentId']>0)
$tree=array_merge($tree,getParents($categorys,$item['parentId']));
$tree[]=$item;
break;
}
}
return $tree;
}
function getParents2($categorys,$catId){
$tree=array();
while($catId != 0){
foreach($categorys as $item){
if($item['categoryId']==$catId){
$tree[]=$item;
$catId=$item['parentId'];
break;
}
}
}
return $tree;
}
$pdo=new PDO('MysqL:host=localhost;dbname=test','root','8888');
$stmt=$pdo->query("select * from category order by categoryId");
$categorys=$stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($result as $item)
echo $item['categoryName'].'
';
echo '
';
foreach($result as $item)
echo str_repeat(' ',$item['level']).$item['categoryName'].'
';
echo '
';
foreach($result as $item)
echo $item['categoryName'].' >> ';
echo '
';
foreach($result as $item)
echo $item['categoryName'].' >> ';
?>
虽然本文介绍的是使用递归来实现的无限级分类,但实际上,并不推荐大家这么做,大家知道分类多了,递归效率也就低了,本文这里仅仅是为了让大家更好的理解递归才这么做的。