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 xml文件操作实现代码(二)
Mar 20 PHP
php checkbox 取值详细说明
Aug 19 PHP
基于flush()不能按顺序输出时的解决办法
Jun 29 PHP
对PHP PDO的一些认识小结
Jan 23 PHP
PHP经典面试题集锦
Mar 19 PHP
PHP定时执行任务的3种方法详解
Dec 21 PHP
php注册登录系统简化版
Dec 28 PHP
ThinkPHP模板循环输出Volist标签用法实例详解
Mar 23 PHP
windows7配置Nginx+php+mysql的详细教程
Sep 04 PHP
PHP验证终端类型是否为手机的简单实例
Feb 07 PHP
解决安装WampServer时提示缺少msvcr110.dll文件的问题
Jul 09 PHP
PHP实现与java 通信的插件使用教程
Aug 11 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中的float类型使用说明
2010/07/27 PHP
解析在PHP中使用全局变量的几种方法
2013/06/24 PHP
php创建session的方法实例详解
2015/01/27 PHP
php获取twitter最新消息的方法
2015/04/14 PHP
PHP魔术方法之__call与__callStatic使用方法
2017/07/23 PHP
小程序微信支付功能配置方法示例详解【基于thinkPHP】
2019/05/05 PHP
javascript获取作用在元素上面的样式属性代码
2012/09/20 Javascript
javaScript年份下拉列表框内容为当前年份及前后50年
2014/05/28 Javascript
jquery validate.js表单验证入门实例(附源码)
2015/11/10 Javascript
基于javascript编写简单日历
2016/05/02 Javascript
JavaScript的ExtJS框架中表格的编写教程
2016/05/21 Javascript
详解Nodejs之静态资源处理
2017/06/05 NodeJs
浅谈 Vue v-model指令的实现原理
2017/06/08 Javascript
Angular4学习笔记router的简单使用
2018/03/30 Javascript
基于jQuery.i18n实现web前端的国际化
2018/05/04 jQuery
JavaScript面向对象继承原理与实现方法分析
2018/08/09 Javascript
解决Vue在封装了Axios后手动刷新页面拦截器无效的问题
2018/11/08 Javascript
一篇文章让你搞懂JavaScript 原型和原型链
2020/11/23 Javascript
Vue项目打包部署到apache服务器的方法步骤
2021/02/01 Vue.js
Python向Excel中插入图片的简单实现方法
2018/04/24 Python
pandas.DataFrame.to_json按行转json的方法
2018/06/05 Python
Python面向对象之反射/自省机制实例分析
2018/08/24 Python
Python可视化工具如何实现动态图表
2020/10/23 Python
html5使用canvas实现跟随光标跳动的火焰效果
2014/01/07 HTML / CSS
HTML5 textarea高度自适应的两种方案
2020/04/08 HTML / CSS
Urban Outfitters英国官网:美国平价服饰品牌
2016/11/25 全球购物
Dune London官网:英国著名奢华鞋履品牌
2017/11/30 全球购物
英国高街电视:High Street TV
2018/05/22 全球购物
亿阳信通股份有限公司C#笔试题
2016/12/06 面试题
语文教育专业推荐信范文
2013/11/25 职场文书
五年级数学教学反思
2014/02/11 职场文书
高三毕业典礼主持词
2014/03/27 职场文书
党支部公开承诺践诺书
2014/03/28 职场文书
公司员工辞职信范文
2015/05/12 职场文书
python文件名批量重命名脚本实例代码
2021/04/22 Python
日本官方排名前10的动漫,名侦探柯南上榜,第一是一部创造历史的动漫
2022/03/18 日漫