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和ACCESS写聊天室(九)
Oct 09 PHP
自动分页的不完整解决方案
Jan 12 PHP
简单示例AJAX结合PHP代码实现登录效果代码
Jul 25 PHP
php中使用parse_url()对网址进行解析的实现代码(parse_url详解)
Jan 03 PHP
php获取ip的三个属性区别介绍(HTTP_X_FORWARDED_FOR,HTTP_VIA,REMOTE_ADDR)
Sep 23 PHP
php连接Access数据库错误及解决方法
Jun 20 PHP
js限制checkbox勾选的个数以及php获取多个checkbbox的方法深入解析
Jul 18 PHP
PHP截断标题且兼容utf8和gb2312编码
Sep 22 PHP
PHP实现通过正则表达式替换回调的内容标签
Jun 15 PHP
php计算整个mysql数据库大小的方法
Jun 19 PHP
CodeIgniter配置之database.php用法实例分析
Jan 20 PHP
自制PHP框架之路由与控制器
May 07 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
php+mysql 实现身份验证代码
2010/03/24 PHP
thinkPHP的表达式查询用法详解
2016/09/14 PHP
Yii2-GridView 中让关联字段带搜索和排序功能示例
2017/01/21 PHP
jquery 表格分页等操作实现代码(pagedown,pageup)
2010/04/11 Javascript
两种不同的方法实现js对checkbox进行全选和反选
2014/05/13 Javascript
使用FlexiGrid实现Extjs表格效果方法分享
2014/12/16 Javascript
javascript白色简洁计算器
2015/05/04 Javascript
js去除浏览器默认底图的方法
2015/06/08 Javascript
文本框只能输入数字的实现方法(兼容IE火狐)
2016/06/25 Javascript
vue.js移动端tab组件的封装实践实例
2017/06/30 Javascript
vue params、query传参使用详解
2017/09/12 Javascript
vue 实现类似淘宝星级评分的示例
2018/03/01 Javascript
vue中使用cookies和crypto-js实现记住密码和加密的方法
2018/10/18 Javascript
深入浅析js原型链和vue构造函数
2018/10/25 Javascript
微信小程序常用的3种提示弹窗实现详解
2019/09/19 Javascript
详解Vue.js 作用域、slot用法(单个slot、具名slot)
2019/10/15 Javascript
vue.js自定义组件实现v-model双向数据绑定的示例代码
2020/01/08 Javascript
js实现点击生成随机div
2020/01/16 Javascript
Vue页面渲染中key的应用实例教程
2021/01/12 Vue.js
巧用Python装饰器 免去调用父类构造函数的麻烦
2012/05/18 Python
启动Atom并运行python文件的步骤
2018/11/09 Python
python requests爬取高德地图数据的实例
2018/11/10 Python
Django stark组件使用及原理详解
2019/08/22 Python
css3一款3D字体带阴影效果的实现步骤
2013/03/20 HTML / CSS
使用CSS3的背景渐变Text Gradient 创建文字颜色渐变
2014/08/19 HTML / CSS
纯CSS3制作页面切换效果的实例代码
2019/05/30 HTML / CSS
幼儿园父亲节活动方案
2014/03/11 职场文书
校企合作协议书
2014/04/16 职场文书
先进典型事迹材料
2014/12/29 职场文书
2015年环卫工作总结
2015/04/28 职场文书
2015年酒店工作总结
2015/04/28 职场文书
2015年中秋放假通知范文
2015/08/18 职场文书
学习社交礼仪心得体会
2016/01/22 职场文书
Vue-Element-Admin集成自己的接口实现登录跳转
2021/06/23 Vue.js
Nginx配置之实现多台服务器负载均衡
2021/08/02 Servers
python神经网络 使用Keras构建RNN训练
2022/05/04 Python