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中使用Oracle数据库(4)
Oct 09 PHP
快速开发一个PHP扩展图文教程
Dec 12 PHP
PHP 中文乱码解决办法总结分析
Jul 30 PHP
PHP函数in_array()使用详解
Aug 20 PHP
Laravel 5 学习笔记
Mar 06 PHP
利用PHP绘图函数实现简单验证码功能的方法
Oct 18 PHP
php生出随机字符串
Jul 06 PHP
PHP机器学习库php-ml的简单测试和使用方法
Jul 14 PHP
PHP实现用户登录的案例代码
May 10 PHP
php微信公众号开发之简答题
Oct 20 PHP
PHP XML Expat解析器知识点总结
Feb 15 PHP
thinkPHP+LayUI 流加载实现功能
Sep 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缓冲 output_buffering和ob_start使用介绍
2014/01/30 PHP
php将远程图片保存到本地服务器的实现代码
2015/08/03 PHP
学习php设计模式 php实现工厂模式(factory)
2015/12/07 PHP
详解PHP防止直接访问.php 文件的实现方法
2017/07/28 PHP
浅谈PHP封装CURL
2019/03/06 PHP
ThinkPHP5.1表单令牌Token失效问题的解决
2019/03/22 PHP
php查看一个变量的占用内存的实例代码
2020/03/29 PHP
tp5.1 框架查询表达式用法详解
2020/05/25 PHP
Add Formatted Data to a Spreadsheet
2007/06/12 Javascript
Extjs在exlipse中设置自动提示的方法
2010/04/07 Javascript
js过滤特殊字符输入适合输入、粘贴、拖拽多种情况
2014/03/22 Javascript
JS拖拽插件实现步骤
2015/08/03 Javascript
jquery通过name属性取值的简单实现方法
2016/06/20 Javascript
简单理解vue中track-by属性
2016/10/26 Javascript
JavaScript实现邮箱地址自动匹配功能代码
2016/11/28 Javascript
JS经典正则表达式笔试题汇总
2016/12/15 Javascript
JavaScript 详解预编译原理
2017/01/22 Javascript
JS+html5制作简单音乐播放器
2020/09/13 Javascript
浅谈Vue.js中的v-on(事件处理)
2017/09/05 Javascript
图文介绍Vue父组件向子组件传值
2018/02/17 Javascript
Vue使用json-server进行后端数据模拟功能
2018/04/17 Javascript
浅谈vuex actions和mutation的异曲同工
2018/12/13 Javascript
详解vue项目中调用百度地图API使用方法
2019/04/25 Javascript
对layui中table组件工具栏的使用详解
2019/09/19 Javascript
[19:59]2014DOTA2国际邀请赛 IG战队纪录片
2014/08/07 DOTA
[02:23]2016国际邀请赛中国区预选赛wings晋级之路
2016/06/29 DOTA
Python中使用PDB库调试程序
2015/04/05 Python
浅谈python 里面的单下划线与双下划线的区别
2017/12/01 Python
Python实现Singleton模式的方式详解
2019/08/08 Python
python list数据等间隔抽取并新建list存储的例子
2019/11/27 Python
Python通过类的组合模拟街道红绿灯
2020/09/16 Python
什么是Connection-oriented Protocol/Connectionless Protocol面向连接的协议/无连接协议
2012/09/06 面试题
校长师德师风自我剖析材料
2014/09/29 职场文书
经典爱情感言
2015/08/03 职场文书
3招让你摆脱即兴讲话冷场尴尬
2019/08/08 职场文书
python数字图像处理之图像自动阈值分割示例
2022/06/28 Python