php 无限级分类学习参考之对ecshop无限级分类的解析 带详细注释


Posted in PHP onMarch 23, 2010
function cat_options($spec_cat_id, $arr) 
{ 
static $cat_options = array(); 
if (isset($cat_options[$spec_cat_id])) 
{ 
return $cat_options[$spec_cat_id]; 
} 
/* 
初始化关键参数: 
$level:当前子节点深度 
$last_cat_id:当前父节点ID 
$options:带有缩进级别的数组 
$cat_id_array:沿同一路径的父节点依次进驻 
$level_array:该节点的子节点深度,也是依次进驻 
*/ 
if (!isset($cat_options[0])) 
{ 
$level = $last_cat_id = 0; 
$options = $cat_id_array = $level_array = array(); 
while (!empty($arr))//如果还有待构造的节点则继续遍历 
{ 
foreach ($arr AS $key => $value) 
{ 
$cat_id = $value['cat_id']; 
//一级分类结点 
if ($level == 0 && $last_cat_id == 0) 
{ 
if ($value['parent_id'] > 0) 
{ 
break; 
} 
$options[$cat_id] = $value; 
$options[$cat_id]['level'] = $level; 
$options[$cat_id]['id'] = $cat_id; 
$options[$cat_id]['name'] = $value['cat_name']; 
//遍历过了就不再遍历 
unset($arr[$key]); 
if ($value['has_children'] == 0) 
{ 
continue; 
} 
$last_cat_id = $cat_id;//下层结点的父亲结点 
$cat_id_array = array($cat_id); 
$level_array[$last_cat_id] = ++$level; 
continue; 
} 
//当前结点的父亲结点ID等于它的上一级结点ID 
if ($value['parent_id'] == $last_cat_id) 
{ 
$options[$cat_id] = $value; 
$options[$cat_id]['level'] = $level; 
$options[$cat_id]['id'] = $cat_id; 
$options[$cat_id]['name'] = $value['cat_name']; 
unset($arr[$key]);//遍历过了就不再遍历 
//如果当前结点有孩子则当前结点要进驻,但不再遍历;反之不进驻也不再遍历 
if ($value['has_children'] > 0) 
{ 
if (end($cat_id_array) != $last_cat_id) 
{ 
$cat_id_array[] = $last_cat_id; 
} 
$last_cat_id = $cat_id;//当现结点做为下一级结点的新的父亲结点 
$cat_id_array[] = $cat_id;//进驻 $level_array[$last_cat_id] = ++$level;//当前结点的下一级结点深度 
} 
} 
elseif ($value['parent_id'] > $last_cat_id) 
{//如果当前结点父亲深度大于目前父亲结点的深度则进行下一轮循环 
break; 
} 
}//endforeach 
$count = count($cat_id_array); 
if ($count > 1) 
{ 
//取出最后进驻的父亲节点作为当前父亲节点 
$last_cat_id = array_pop($cat_id_array); 
} 
elseif ($count == 1) 
{ 
if ($last_cat_id != end($cat_id_array)) 
{ 
//进驻的父亲结点只有一个时并且没有作为当前父亲节点时把它取出 
$last_cat_id = end($cat_id_array); 
} 
else 
{ //否则最后取出的父亲结点一定是一级分类结点 
$level = 0; 
$last_cat_id = 0; 
$cat_id_array = array(); 
continue; 
} 
} 
if ($last_cat_id && isset($level_array[$last_cat_id])) 
{ 
//取出当前结点的深度 
$level = $level_array[$last_cat_id]; 
} 
else 
{ 
$level = 0; 
} 
}//end while,此时已完成非递归前序遍历构造树的工作,其中$options已保存了从根结点开始的所有结点带有分层性质的数组 
$cat_options[0] = $options; 
} 
else 
{ 
$options = $cat_options[0]; 
} 
//如果从0开始即取整个树则直接返回不再处理. 
if (!$spec_cat_id) 
{ 
return $options; 
} 
//否则开始从指定结点截取,以下比较简单我还是稍微说说吧,要说就说几个参数含义吧 
/* 
$spec_cat_id_level:截取结点的深度 
$spec_cat_id_array:最终返回的以该结点为根结点的一棵商品分类树 
最终返回的数组是这样排序的:按父亲结点大小,按直接父亲结点,按同一父亲结点这样的先根遍历,具个例子: 
一级结点有1,5 二级结点有2,6,7 三级结点有8,9,如果1的直接孩子是2,6而2的直接孩子是8,9;另外 
5的直接孩子是7那么最终的数组是这样排列的1->2->8->9->6->5->7 
*/ 
else 
{ 
if (empty($options[$spec_cat_id])) 
{ 
return array(); 
} 
$spec_cat_id_level = $options[$spec_cat_id]['level']; 
foreach ($options AS $key => $value) 
{ 
if ($key != $spec_cat_id) 
{ 
unset($options[$key]); 
} 
else 
{ 
break; 
} 
} 
$spec_cat_id_array = array(); 
foreach ($options AS $key => $value) 
{ 
if (($spec_cat_id_level == $value['level'] && $value['cat_id'] != $spec_cat_id) || 
($spec_cat_id_level > $value['level'])) 
{ 
break; 
} 
else 
{ 
$spec_cat_id_array[$key] = $value; 
} 
} 
$cat_options[$spec_cat_id] = $spec_cat_id_array; 
return $spec_cat_id_array; 
} 
}
PHP 相关文章推荐
PHP调用JAVA的WebService简单实例
Mar 11 PHP
php+xml实现在线英文词典之添加词条的方法
Jan 23 PHP
php实现检查文章是否被百度收录
Jan 27 PHP
PHP使用strtotime计算两个给定日期之间天数的方法
Mar 18 PHP
php实现插入排序
Mar 29 PHP
php实现用已经过去多长时间的方式显示时间
Jun 05 PHP
PHP如何通过传引用的思想实现无限分类(代码简单)
Oct 13 PHP
CI框架数据库查询之join用法分析
May 18 PHP
探究Laravel使用env函数读取环境变量为null的问题
Dec 06 PHP
thinkPHP3.2.2框架行为扩展及demo示例
Jun 19 PHP
PHP实现获取毫秒时间戳的方法【使用microtime()函数】
Mar 01 PHP
PHP判断当前使用的是什么浏览器(推荐)
Oct 27 PHP
PHP提取数据库内容中的图片地址并循环输出
Mar 21 #PHP
mysql From_unixtime及UNIX_TIMESTAMP及DATE_FORMAT日期函数
Mar 21 #PHP
PHP中10个不常见却非常有用的函数
Mar 21 #PHP
初次接触php抽象工厂模式(Elgg)
Mar 21 #PHP
PHP5与MySQL数据库操作常用代码 收集
Mar 21 #PHP
ajax+php打造进度条 readyState各状态
Mar 20 #PHP
elgg 获取文件图标地址的方法
Mar 20 #PHP
You might like
深入PHP运行环境配置的详解
2013/06/04 PHP
php实现水仙花数的4个示例分享
2014/04/08 PHP
JavaScript类和继承 constructor属性
2010/03/04 Javascript
怎么通过onclick事件获取js函数返回值(代码少)
2015/07/28 Javascript
JavaScript  cookie 跨域访问之广告推广
2016/04/20 Javascript
javascript的replace方法结合正则使用实例总结
2016/06/16 Javascript
javascript类型系统_正则表达式RegExp类型详解
2016/06/24 Javascript
基于JavaScript实现复选框的全选和取消全选
2017/02/09 Javascript
layui选项卡效果实现代码
2017/05/19 Javascript
浅谈Angular 中何时取消订阅
2017/11/22 Javascript
详解React中合并单元格的正确写法
2019/01/08 Javascript
node.js中express模块创建服务器和http模块客户端发请求
2019/03/06 Javascript
JavaScript动态检测密码强度原理及实现方法详解
2019/06/11 Javascript
微信小程序实现一张或多张图片上传(云开发)
2019/09/25 Javascript
javascript实现一款好看的秒表计时器
2020/09/05 Javascript
多种类型jQuery网页验证码插件代码实例
2021/01/09 jQuery
使用python实现扫描端口示例
2014/03/29 Python
python中类的一些方法分析
2014/09/25 Python
深入理解python函数递归和生成器
2016/06/06 Python
学习Python3 Dlib19.7进行人脸面部识别
2018/01/24 Python
Windows下将Python文件打包成.EXE可执行文件的方法
2018/08/03 Python
Django model反向关联名称的方法
2018/12/15 Python
我用Python抓取了7000 多本电子书案例详解
2019/03/25 Python
python将字符串转变成dict格式的实现
2019/11/18 Python
使用Python爬虫库requests发送表单数据和JSON数据
2020/01/25 Python
pycharm第三方库安装失败的问题及解决经验分享
2020/05/09 Python
Python collections.defaultdict模块用法详解
2020/06/18 Python
解锁canvas导出图片跨域的N种姿势小结
2019/01/24 HTML / CSS
Java面试中常遇到的问题,也是需要注意的几点
2013/08/30 面试题
物业管理应届生求职信
2013/10/28 职场文书
不打扫卫生检讨书
2014/02/12 职场文书
工程质量月活动方案
2014/02/19 职场文书
2014年入党积极分子党校培训心得体会
2014/07/08 职场文书
主要领导对照检查材料
2014/08/26 职场文书
会计求职自荐信
2015/03/26 职场文书
PHP解决高并发问题
2021/04/01 PHP