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 相关文章推荐
Apache2 httpd.conf 中文版
Nov 17 PHP
php下使用strpos需要注意 === 运算符
Jul 17 PHP
合并ThinkPHP配置文件以消除代码冗余的实现方法
Jul 22 PHP
PHP中几个可以提高运行效率的代码写法、技巧分享
Aug 21 PHP
PHP中的output_buffering详细介绍
Sep 27 PHP
php检测数组长度函数sizeof与count用法
Nov 17 PHP
php输入数据统一类实例
Feb 23 PHP
Linux系统下php获得系统分区信息的方法
Mar 30 PHP
PHP 中 Orientation 属性判断上传图片是否需要旋转
Oct 16 PHP
PHP模板引擎Smarty内建函数foreach,foreachelse用法分析
Apr 11 PHP
php实现数组纵向转横向并过滤重复值的方法分析
May 29 PHP
PHP命名空间与自动加载类详解
Sep 04 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 获取客户端真实IP地址多种方法小结
2010/05/15 PHP
php学习笔记 php中面向对象三大特性之一[封装性]的应用
2011/06/13 PHP
php返回json数据函数实例
2014/10/09 PHP
PHP中使用GD库绘制折线图 折线统计图的绘制方法
2015/11/09 PHP
TP5框架安全机制实例分析
2020/04/05 PHP
javascript 树控件 比较好用
2009/06/11 Javascript
javascript编码的几个方法详细介绍
2013/01/06 Javascript
JavaScript通过function定义对象并给对象添加toString()方法实例分析
2015/03/23 Javascript
简介JavaScript中的unshift()方法的使用
2015/06/09 Javascript
提升jQuery的性能需要做好七件事
2016/01/11 Javascript
多种方式实现js图片预览
2016/12/12 Javascript
JS实现本地存储信息的方法(基于localStorage与userData)
2017/02/18 Javascript
分享一个精简的vue.js 图片lazyload插件实例
2017/03/13 Javascript
JS判断两个对象内容是否相等的方法示例
2017/04/10 Javascript
vue和webpack打包项目相对路径修改的方法
2018/06/15 Javascript
Vue实现导航栏点击当前标签变色功能
2020/08/19 Javascript
基于axios 的responseType类型的设置方法
2019/10/29 Javascript
vue quill editor 使用富文本添加上传音频功能
2020/01/14 Javascript
基于JavaScript实现表格隔行换色
2020/05/08 Javascript
基于Vue中的父子传值问题解决
2020/07/27 Javascript
Vue数组响应式操作及高阶函数使用代码详解
2020/08/01 Javascript
Python中使用PyQt把网页转换成PDF操作代码实例
2015/04/23 Python
Python实现批量下载图片的方法
2015/07/08 Python
Python读取文件内容为字符串的方法(多种方法详解)
2020/03/04 Python
PyQt5实现画布小程序
2020/05/30 Python
scrapy-splash简单使用详解
2021/02/21 Python
迷你分体式空调:SoGoodToBuy
2018/08/07 全球购物
哈萨克斯坦最大的时装、鞋子和配饰在线商店:Lamoda.kz
2019/11/19 全球购物
sort命令的作用和用法
2012/11/04 面试题
宣传策划类求职信范文
2014/01/31 职场文书
纪念九一八事变演讲稿:牢记九一八,屈辱怎能忘
2014/09/14 职场文书
关于童年的读书笔记
2015/06/26 职场文书
工伤调解协议书
2016/03/21 职场文书
2016年社区“我们的节日·中秋节”活动总结
2016/04/05 职场文书
解析CSS 提取图片主题色功能(小技巧)
2021/05/12 HTML / CSS
Django rest framework如何自定义用户表
2021/06/09 Python