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转成EXE文件
Oct 09 PHP
ASP和PHP都是可以删除自身的
Apr 09 PHP
php Undefined index的问题
Jun 01 PHP
PHP三元运算的2种写法代码实例
May 12 PHP
destoon出现验证码不显示时的紧急处理方法
Aug 22 PHP
PHP+FFMPEG实现将视频自动转码成H264标准Mp4文件
Sep 24 PHP
PHP实现模仿socket请求返回页面的方法
Nov 04 PHP
详解WordPress中给链接添加查询字符串的方法
Dec 18 PHP
Yii隐藏URL中index.php的方法
Jul 12 PHP
PHP实现登陆并抓取微信列表中最新一组微信消息的方法
Jul 10 PHP
使用XHProf查找PHP性能瓶颈的实例
Dec 13 PHP
php新建文件的方法实例
Sep 26 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循环输出数据库内容的代码
2008/05/24 PHP
总结一些PHP中好用但又容易忽略的小知识
2017/06/02 PHP
利用php操作memcache缓存的基础方法示例
2017/08/02 PHP
基于thinkphp6.0的success、error实现方法
2019/11/05 PHP
js 获取子节点函数 (兼容FF与IE)
2010/04/18 Javascript
jQuery对表单的操作代码集合
2011/04/06 Javascript
JavaScript高级程序设计 阅读笔记(十三) js定义类或对象
2012/08/14 Javascript
jQuery.fn和jQuery.prototype区别介绍
2013/10/05 Javascript
JS按字节截取字符长度实例
2013/11/20 Javascript
javascript实现input file上传图片预览效果
2015/12/31 Javascript
JavaScript知识点总结之如何提高性能
2016/01/15 Javascript
JS JSOP跨域请求实例详解
2016/07/04 Javascript
javascript实现根据汉字获取简拼
2016/09/25 Javascript
livereload工具实现前端可视化开发【推荐】
2016/12/23 Javascript
JS编写函数实现对身份证号码最后一位的验证功能
2016/12/29 Javascript
如何在Angular2中使用jQuery及其插件的方法
2017/02/09 Javascript
详解JS中遍历语法的比较
2017/04/07 Javascript
JavaScript之json_动力节点Java学院整理
2017/06/29 Javascript
详解Vue的computed(计算属性)使用实例之TodoList
2017/08/07 Javascript
微信小程序实现刷脸登录
2018/05/25 Javascript
vue 设置路由的登录权限的方法
2018/07/03 Javascript
vue-cli4项目开启eslint保存时自动格式问题
2020/07/13 Javascript
vue 解决无法对未定义的值,空值或基元值设置反应属性报错问题
2020/07/31 Javascript
python实现从web抓取文档的方法
2014/09/26 Python
Python安装模块的常见问题及解决方法
2018/02/05 Python
Python字符串中添加、插入特定字符的方法
2019/09/10 Python
html2canvas生成的图片偏移不完整的解决方法
2020/05/19 HTML / CSS
超市促销实习自我鉴定
2013/09/23 职场文书
工作会议欢迎词
2014/01/16 职场文书
浙大毕业生自荐信
2014/01/26 职场文书
办护照工作证明
2014/10/01 职场文书
2014年学生党支部工作总结
2014/12/20 职场文书
拾金不昧表扬信
2015/01/16 职场文书
盲山观后感
2015/06/11 职场文书
世界十大评分最高的动漫,CLANNAD上榜,第八赚足人们眼泪
2022/03/18 日漫
开发微信小程序之WXSS样式教程
2022/04/18 HTML / CSS