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中的Class的几点个人看法
Oct 09 PHP
检查url链接是否已经有参数的php代码 添加 ? 或 &
Feb 09 PHP
JSON在PHP中的应用介绍
Sep 08 PHP
PHP5函数小全(分享)
Jun 06 PHP
PHP动态生成javascript文件的2个例子
Apr 11 PHP
PHP面向对象教程之自定义类
Jun 10 PHP
Yii2中事务的使用实例代码详解
Sep 07 PHP
php实现登陆模块功能示例
Oct 20 PHP
php实现产品加入购物车功能(1)
Jul 23 PHP
PHP实现限制IP访问的方法
Apr 20 PHP
对于Laravel 5.5核心架构的深入理解
Feb 22 PHP
使用ucenter实现多站点同步登录的讲解
Mar 21 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
php5 pdo新改动加载注意事项
2008/09/11 PHP
PHP 面向对象 final类与final方法
2010/05/05 PHP
PHP实现今天是星期几的几种写法
2013/09/26 PHP
Yii1.1框架实现PHP极光推送消息通知功能
2018/09/06 PHP
document.getElementById介绍
2011/09/13 Javascript
JavaScript入门之基本函数详解
2011/10/21 Javascript
JavaScript 函数参数是传值(byVal)还是传址(byRef) 分享
2013/07/02 Javascript
纯js分页代码(简洁实用)
2013/11/05 Javascript
如何设置一定时间内只能发送一次请求
2014/02/28 Javascript
node.js中的fs.mkdir方法使用说明
2014/12/17 Javascript
简介JavaScript中search()方法的使用
2015/06/06 Javascript
javascript实现随机显示星星特效
2016/01/28 Javascript
基于javascript实现tab切换特效
2016/03/29 Javascript
深入理解jQuery事件绑定
2016/06/02 Javascript
js弹出窗口简单实现代码
2017/03/22 Javascript
Vue中添加手机验证码组件功能操作方法
2017/12/07 Javascript
JavaScript累加、迭代、穷举、递归等常用算法实例小结
2018/05/08 Javascript
解决LayUI表单获取不到data的问题
2018/08/20 Javascript
js jquery 获取某一元素到浏览器顶端的距离实现方法
2018/09/05 jQuery
Vue-component全局注册实例
2018/09/06 Javascript
原生JS使用Canvas实现拖拽式绘图功能
2019/06/05 Javascript
Vue使用lodop实现打印小结
2019/07/06 Javascript
vue项目实现设置根据路由高亮对应的菜单项操作
2020/08/06 Javascript
python处理文本文件实现生成指定格式文件的方法
2014/07/31 Python
python判断一个集合是否包含了另外一个集合中所有项的方法
2015/06/30 Python
Python实现抢购IPhone手机
2018/02/07 Python
Python解决两个整数相除只得到整数部分的实例
2018/11/10 Python
pandas ix &iloc &loc的区别
2019/01/10 Python
UNIONBAY官网:美国青少年服装品牌
2019/03/26 全球购物
如何查看在weblogic中已经发布的EJB
2012/06/01 面试题
利用promise及参数解构封装ajax请求的方法
2021/03/24 Javascript
党委班子对照检查材料
2014/08/19 职场文书
教育教学工作反思
2016/02/24 职场文书
情况说明书格式及范文
2019/06/24 职场文书
《飘》英文读后感五篇
2019/10/11 职场文书
一起来看看Vue的核心原理剖析
2022/03/24 Vue.js