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 5.0对象模型深度探索之属性和方法
Mar 27 PHP
PHP 命令行参数详解及应用
May 18 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(四)
Jun 23 PHP
Windows下安装PHP单元测试环境PHPUnit图文教程
Oct 24 PHP
PHP函数extension_loaded()用法实例
Jan 19 PHP
php生成唯一的订单函数分享
Feb 02 PHP
在PHP站点的页面上添加Facebook评论插件的实例教程
Jan 08 PHP
PHP和MySql中32位和64位的整形范围是多少
Feb 18 PHP
php把时间戳转换成多少时间之前函数的实例
Nov 16 PHP
php获取目录中所有文件名及判断文件与目录的简单方法
Mar 04 PHP
thinkPHP5.0框架开发规范简介
Mar 25 PHP
Yii 实现数据加密和解密
Mar 09 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面向对象程序设计之对象的遍历操作示例
2019/06/12 PHP
JavaScript中this关键字使用方法详解
2007/03/08 Javascript
匹配任意字符的正则表达式写法
2010/04/29 Javascript
jQuery.ajax 用户登录验证代码
2010/10/29 Javascript
jWiard 基于JQuery的强大的向导控件介绍
2011/10/28 Javascript
基于NodeJS的前后端分离的思考与实践(二)模版探索
2014/09/26 NodeJs
JavaScript设计模式之建造者模式介绍
2014/12/28 Javascript
基于jQuery实现仿QQ空间送礼物功能代码
2016/05/24 Javascript
AngularJS基础 ng-paste 指令简单示例
2016/08/02 Javascript
AngularJS定时器的使用与移除操作方法【interval与timeout】
2016/12/14 Javascript
微信小程序 限制1M的瘦身技巧与方法详解
2017/01/06 Javascript
jQuery ajax读取本地json文件的实例
2017/10/31 jQuery
Vue.js获取被选择的option的value和text值方法
2018/08/24 Javascript
element-ui中的select下拉列表设置默认值方法
2018/08/24 Javascript
three.js显示中文字体与tween应用详析
2021/01/04 Javascript
python使用PIL模块实现给图片打水印的方法
2015/05/22 Python
python魔法方法-自定义序列详解
2016/07/21 Python
Python Django使用forms来实现评论功能
2016/08/17 Python
Python快速排序算法实例分析
2017/11/29 Python
Python标准库笔记struct模块的使用
2018/02/22 Python
Python使用sorted对字典的key或value排序
2018/11/15 Python
Python调用C/C++的方法解析
2020/08/05 Python
美国折扣香水网站:The Perfume Spot
2020/12/12 全球购物
房地产销售大学生自我评价分享
2013/11/11 职场文书
安卓程序员求职信
2014/02/28 职场文书
工作评语大全
2014/04/26 职场文书
竞选团支书演讲稿
2014/04/28 职场文书
民主生活会发言材料
2014/10/20 职场文书
违反工作规定检讨书范文
2014/12/14 职场文书
亚布力滑雪场导游词
2015/02/09 职场文书
医院消毒隔离制度
2015/08/05 职场文书
2016年学校党支部公开承诺书
2016/03/25 职场文书
Nginx域名转发使用场景代码实例
2021/03/31 Servers
使用vue-element-admin框架从后端动态获取菜单功能的实现
2021/04/29 Vue.js
据Python爬虫不靠谱预测可知今年双十一销售额将超过6000亿元
2021/11/11 Python
解决 Redis 秒杀超卖场景的高并发
2022/04/12 Redis