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数据库操作面向对象的优点
Oct 09 PHP
php 操作数组(合并,拆分,追加,查找,删除等)
Jul 20 PHP
PHP 自定义错误处理函数的使用详解
May 10 PHP
php 无限级分类,超级简单的无限级分类,支持输出树状图
Jun 29 PHP
百度实时推送api接口应用示例
Oct 21 PHP
PHP 双链表(SplDoublyLinkedList)简介和使用实例
May 12 PHP
thinkphp autoload 命名空间自定义 namespace
Jul 17 PHP
PHP函数func_num_args用法实例分析
Dec 07 PHP
PHP微信刮刮卡 附微信接口
Jul 22 PHP
php实现HTML实体编号与非ASCII字符串相互转换类实例
Nov 02 PHP
PHP不使用内置函数实现字符串转整型的方法示例
Jul 03 PHP
PHP filter_var() 函数, 验证判断EMAIL,URL等
Mar 09 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中sql注入漏洞示例 sql注入漏洞修复
2014/01/24 PHP
php基于curl主动推送最新内容给百度收录的方法
2016/10/14 PHP
PHP实现活动人选抽奖功能
2017/04/19 PHP
自己动手开发jQuery插件教程
2011/08/25 Javascript
javascript针对DOM的应用分析(四)
2012/04/15 Javascript
Jquery 动态循环输出表格具体方法
2013/11/23 Javascript
键盘KeyCode值列表汇总
2013/11/26 Javascript
一张表格告诉你windows.onload()与$(document).ready()的区别
2014/05/16 Javascript
JavaScript中的闭包介绍
2015/03/15 Javascript
jquery-tips悬浮提示插件分享
2015/07/31 Javascript
Bootstrap实现响应式导航栏效果
2015/12/28 Javascript
浅谈javascript基础之客户端事件驱动
2016/06/10 Javascript
jQuery中JSONP的两种实现方式详解
2016/09/26 Javascript
原生js实现焦点轮播图效果
2017/01/12 Javascript
利用Javascript裁剪图片并存储的简单实现
2017/03/13 Javascript
jQuery Validate插件ajax方式验证输入值的实例
2017/12/21 jQuery
微信小程序实现image组件图片自适应宽度比例显示的方法
2018/01/16 Javascript
iView-admin 动态路由问题的解决方法
2018/10/03 Javascript
微信接入之获取用户头像的方法步骤
2019/09/23 Javascript
基于iview-admin实现动态路由的示例代码
2019/10/02 Javascript
在vue中使用echars实现上浮与下钻效果
2019/11/08 Javascript
Vue基础配置讲解
2019/11/29 Javascript
js将URL网址转为16进制加密与解密函数
2020/03/04 Javascript
Python2.x版本中基本的中文编码问题解决
2015/10/12 Python
Python使用pyh生成HTML文档的方法示例
2018/03/10 Python
python在每个字符后添加空格的实例
2018/05/07 Python
Python实现检测文件的MD5值来查找重复文件案例
2020/03/12 Python
如何在pycharm中安装第三方包
2020/10/27 Python
购买澳大利亚最好的服装和内衣在线:BONDS
2016/10/14 全球购物
波兰家具和室内装饰品购物网站:Vivre
2018/04/10 全球购物
EMU Australia澳大利亚官网:澳大利亚本土雪地靴品牌
2019/07/24 全球购物
德国咖啡批发商:Coffeefair
2019/08/26 全球购物
黑猩猩商店:The Chimp Store
2020/02/12 全球购物
服装电子商务创业计划书
2014/01/30 职场文书
武当山导游词
2015/02/03 职场文书
SQLServer常见数学函数梳理总结
2022/08/05 MySQL