PHP无限分类(树形类)


Posted in PHP onSeptember 28, 2013
<?php
//模拟PHP无限分类查询结果
return array(
    array(
        'id'=>1,
        'pid'=>0,
        'name'=>'主页'
    ),
    array(
        'id'=>2,
        'pid'=>0,
        'name'=>'新闻'
    ),
    array(
        'id'=>3,
        'pid'=>0,
        'name'=>'媒体'
    ),
    array(
        'id'=>4,
        'pid'=>0,
        'name'=>'下载'
    ),
    array(
        'id'=>5,
        'pid'=>0,
        'name'=>'关于我们'
    ),
    array(
        'id'=>6,
        'pid'=>2,
        'name'=>'天朝新闻'
    ),
    array(
        'id'=>7,
        'pid'=>2,
        'name'=>'海外新闻'
    ),
    array(
        'id'=>8,
        'pid'=>6,
        'name'=>'州官新闻'
    ),
    array(
        'id'=>9,
        'pid'=>3,
        'name'=>'音乐'
    ),
    array(
        'id'=>10,
        'pid'=>3,
        'name'=>'电影'
    ),
    array(
        'id'=>11,
        'pid'=>3,
        'name'=>'小说'
    ),
    array(
        'id'=>12,
        'pid'=>9,
        'name'=>'铃声'
    ),
    array(
        'id'=>13,
        'pid'=>9,
        'name'=>'流行音乐'
    ),
    array(
        'id'=>14,
        'pid'=>9,
        'name'=>'古典音乐'
    ),
    array(
        'id'=>15,
        'pid'=>12,
        'name'=>'热门铃声'
    ),
    array(
        'id'=>16,
        'pid'=>12,
        'name'=>'搞笑铃声'
    ),
    array(
        'id'=>17,
        'pid'=>12,
        'name'=>'MP3铃声'
    ),
    array(
        'id'=>18,
        'pid'=>17,
        'name'=>'128K'
    ),
    array(
        'id'=>19,
        'pid'=>8,
        'name'=>'娱乐新闻'
    ),
    array(
        'id'=>20,
        'pid'=>11,
        'name'=>'穿越类'
    ),
    array(
        'id'=>21,
        'pid'=>11,
        'name'=>'武侠类'
    ),
);
?>

     拉风归拉风,但是那些文章提供的无限分类的类相关操作有点挫,直接把对数据库操作也封装进去了。也就是别人要用你这个类,还要跟你建一样的表,真TM恶心。由于项目要用到,所以自己写了一个PHP无限分类的类(也称树形类),没有数据库的操作,只需要实例化的时候传进去结果集,也就是树形数组。再执行leaf方法或navi方法即可得到想要的结果,下面请看源码,看完之后奉上smarty模板引擎的相应的模板递归方法。

<?php
/**
 * Tree 树型类(无限分类)
 *
 * @author Kvoid
 * @copyright http://kvoid.com
 * @version 1.0
 * @access public
 * @example
 *   $tree= new Tree($result);
 *   $arr=$tree->leaf(0);
 *   $nav=$tree->navi(15);
 */
class Tree {
    private $result;
    private $tmp;
    private $arr;
    private $already = array();
    /**
     * 构造函数
     *
     * @param array $result 树型数据表结果集
     * @param array $fields 树型数据表字段,array(分类id,父id)
     * @param integer $root 顶级分类的父id
     */
    public function __construct($result, $fields = array('id', 'pid'), $root = 0) {
        $this->result = $result;
        $this->fields = $fields;
        $this->root = $root;
        $this->handler();
    }
    /**
     * 树型数据表结果集处理
     */
    private function handler() {
        foreach ($this->result as $node) {
            $tmp[$node[$this->fields[1]]][] = $node;
        }
        krsort($tmp);
        for ($i = count($tmp); $i > 0; $i--) {
            foreach ($tmp as $k => $v) {
                if (!in_array($k, $this->already)) {
                    if (!$this->tmp) {
                        $this->tmp = array($k, $v);
                        $this->already[] = $k;
                        continue;
                    } else {
                        foreach ($v as $key => $value) {
                            if ($value[$this->fields[0]] == $this->tmp[0]) {
                                $tmp[$k][$key]['child'] = $this->tmp[1];
                                $this->tmp = array($k, $tmp[$k]);
                            }
                        }
                    }
                }
            }
            $this->tmp = null;
        }
        $this->tmp = $tmp;
    }
    /**
     * 反向递归
     */
    private function recur_n($arr, $id) {
        foreach ($arr as $v) {
            if ($v[$this->fields[0]] == $id) {
                $this->arr[] = $v;
                if ($v[$this->fields[1]] != $this->root) $this->recur_n($arr, $v[$this->fields[1]]);
            }
        }
    }
    /**
     * 正向递归
     */
    private function recur_p($arr) {
        foreach ($arr as $v) {
            $this->arr[] = $v[$this->fields[0]];
            if ($v['child']) $this->recur_p($v['child']);
        }
    }
    /**
     * 菜单 多维数组
     *
     * @param integer $id 分类id
     * @return array 返回分支,默认返回整个树
     */
    public function leaf($id = null) {
        $id = ($id == null) ? $this->root : $id;
        return $this->tmp[$id];
    }
    /**
     * 导航 一维数组
     *
     * @param integer $id 分类id
     * @return array 返回单线分类直到顶级分类
     */
    public function navi($id) {
        $this->arr = null;
        $this->recur_n($this->result, $id);
        krsort($this->arr);
        return $this->arr;
    }
    /**
     * 散落 一维数组
     *
     * @param integer $id 分类id
     * @return array 返回leaf下所有分类id
     */
    public function leafid($id) {
        $this->arr = null;
        $this->arr[] = $id;
        $this->recur_p($this->leaf($id));
        return $this->arr;
    }
}
?>

在smarty中的PHP无限分类的使用方法:

$result=$db->query(……);//这里查询得到结果集,注意结果集为数组
$tree= new Tree($result);
$arr=$tree->leaf(0);
$nav=$tree->navi(15);
$smarty->assign(‘arr',$arr);
$smarty->assign(‘nav',$nav);
$smarty->display(‘test.html');

在smarty模板中这样递归:

<!--导航-->
<div id="navigator">
<{foreach $nav as $n}>
    <{if $n@iteration != $n@last}>
        <{$n.name}> ->
    <{else}>
        <{$n.name}>
    <{/if}>
<{/foreach}>
</div>
<!--树形菜单-->
<div id="menu">
<{function name=menu}>
    <ul>
        <{foreach $data as $entry}>
            <li>
                <span><{$entry.name}></span> <{*注意字段要改成自己的字段哦*}>
            <{if isset($entry.child)}>
                <{call name=menu data=$entry.child}>
            <{/if}>
            </li>
        <{/foreach}>
    </ul>
<{/function}>
<{call name=menu data=$arr}> <{*注意在这里$arr才是模板变量*}>
</div>

转载请申明来自kvoid.com

当然,你也可以更改递归方法,用你想的标签不受拘束。HTML+PHP混编的递归方法这里就不贴了,我也懒得写,最讨厌混编,看着恶心,在这里推荐一下jake前辈的SpeedPHP框架,由于默认的引擎是smarty,我的这个PHP无限分类完全兼容SP框架。同样的,jquery的treeview插件和下拉菜单插件也完美支持。

对了,建议使用Smarty强大的缓存功能,缓存才是王道。

PHP 相关文章推荐
php中的MVC模式运用技巧
May 03 PHP
Cannot modify header information错误解决方法
Oct 08 PHP
php操作excel文件 基于phpexcel
Jul 02 PHP
PHP中的错误处理、异常处理机制分析
May 07 PHP
基于initPHP的框架介绍
Apr 18 PHP
php生成二维码的几种方式整理及使用实例
Jun 03 PHP
基于PHP+Ajax实现表单验证的详解
Jun 25 PHP
C#使用PHP服务端的Web Service通信实例
Apr 08 PHP
[原创]ThinkPHP让../Public在模板不解析(直接输出)的方法
Oct 09 PHP
thinkPHP统计排行与分页显示功能示例
Dec 02 PHP
php 常用的系统函数
Feb 07 PHP
laravel实现分页样式替换示例代码(增加首、尾页)
Sep 22 PHP
PHP的PSR规范中文版
Sep 28 #PHP
PHP中time(),date(),mktime()区别介绍
Sep 28 #PHP
php中time()和mktime()方法的区别
Sep 28 #PHP
PHP用strstr()函数阻止垃圾评论(通过判断a标记)
Sep 28 #PHP
PHP利用REFERER根居访问来地址进行页面跳转
Sep 28 #PHP
PHP strstr 函数判断字符串是否否存在的实例代码
Sep 28 #PHP
PHP JS Ip地址及域名格式检测代码
Sep 27 #PHP
You might like
PHPMailer 中文使用说明小结
2010/01/22 PHP
PHP数组循环操作详细介绍 附实例代码
2013/02/03 PHP
PHP传参之传值与传址的区别
2015/04/24 PHP
PHP之浮点数计算比较以及取整数不准确的解决办法
2015/07/29 PHP
Discuz!X中SESSION机制实例详解
2015/09/23 PHP
Yii+MYSQL锁表防止并发情况下重复数据的方法
2016/07/14 PHP
js对象数组按属性快速排序
2011/01/31 Javascript
artdialog的图片/标题以及关闭按钮不显示的解决方法
2013/06/27 Javascript
基于JQuery的列表拖动排序实现代码
2013/10/01 Javascript
jquery导航制件jquery鼠标经过变色效果示例
2013/12/05 Javascript
js离开或刷新页面检测(且兼容FF,IE,Chrome)
2014/03/05 Javascript
jQuery中用dom操作替代正则表达式
2014/12/29 Javascript
javascript制作照片墙及制作过程中出现的问题
2016/04/04 Javascript
基于HTML模板和JSON数据的JavaScript交互(移动端)
2016/04/06 Javascript
jQuery EasyUI Pagination实现分页的常用方法
2016/05/21 Javascript
Jquery组件easyUi实现选项卡切换示例
2016/08/23 Javascript
JavaScript每天必学之事件
2016/09/18 Javascript
使用ionic在首页新闻中应用到的跑马灯效果的实现方法
2017/02/13 Javascript
js实现登录与注册界面
2017/11/01 Javascript
在vue-cli项目中使用bootstrap的方法示例
2018/04/21 Javascript
7个好用的JavaScript技巧分享(译)
2019/05/07 Javascript
jQuery实现的点击显示隐藏下拉菜单功能完整示例
2019/05/17 jQuery
基于layui轮播图满屏是高度自适应的解决方法
2019/09/16 Javascript
[49:20]2014 DOTA2国际邀请赛中国区预选赛5.21 CIS VS TongFu
2014/05/22 DOTA
Python中的列表知识点汇总
2015/04/14 Python
利用Python开发微信支付的注意事项
2016/08/19 Python
基于Python的接口测试框架实例
2016/11/04 Python
对python读取zip压缩文件里面的csv数据实例详解
2019/02/08 Python
Python 按字典dict的键排序,并取出相应的键值放于list中的实例
2019/02/12 Python
Python常见数字运算操作实例小结
2019/03/22 Python
python3 常见解密加密算法实例分析【base64、MD5等】
2019/12/19 Python
自定义Django Form中choicefield下拉菜单选取数据库内容实例
2020/03/13 Python
波兰最大的度假胜地和城市公寓租赁运营商:Sun & Snow
2018/10/18 全球购物
高中生综合素质自我评价
2015/03/06 职场文书
村官2015年度工作总结
2015/10/14 职场文书
2016秋季田径运动会广播稿
2015/12/21 职场文书