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 相关文章推荐
header()函数使用说明
Nov 23 PHP
php5 non-thread-safe和thread-safe这两个版本的区别分析
Mar 13 PHP
php中XMLHttpRequest(Ajax)不能设置自定义的Referer的解决方法
Nov 26 PHP
测试PHP连接MYSQL成功与否的代码
Aug 16 PHP
ThinkPHP快速入门实例教程之数据分页
Jul 01 PHP
让ThinkPHP支持大小写url地址访问的方法
Oct 31 PHP
PHP中使用imagick生成PSD文件缩略图教程
Jan 26 PHP
php上传大文件失败的原因及应对策略
Oct 20 PHP
php同时使用session和cookie来保存用户登录信息的实现代码
May 13 PHP
win10 apache配置虚拟主机后localhost无法使用的解决方法
Jan 27 PHP
PHP实现的只保留字符串首尾字符功能示例【隐藏部分字符串】
Mar 11 PHP
php扩展开发入门demo示例
Sep 23 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代码
2012/06/08 PHP
dedecms中使用php语句指南
2014/11/13 PHP
5 cool javascript apps
2007/03/24 Javascript
原生js实现跨浏览器获取鼠标按键的值
2013/04/08 Javascript
Jquery在指定DIV加载HTML示例代码
2014/02/17 Javascript
js字符串完全替换函数分享
2014/12/03 Javascript
web前端设计师们常用的jQuery特效插件汇总
2014/12/07 Javascript
ajax如何实现页面局部跳转与结果返回
2015/08/24 Javascript
JS数组排序技巧汇总(冒泡、sort、快速、希尔等排序)
2015/11/24 Javascript
jQuery的内容过滤选择器学习教程
2016/04/18 Javascript
js实现精确到毫秒的倒计时效果
2016/08/05 Javascript
JS中this上下文对象使用方式
2016/10/09 Javascript
js+html制作简单验证码
2017/02/16 Javascript
Bootstrap Tree View简单而优雅的树结构组件实例解析
2017/06/15 Javascript
JavaScript比较同一天的时间大小实例代码
2018/02/09 Javascript
IE11下CKEditor在Bootstrap Modal中下拉问题的解决
2019/09/25 Javascript
Python中join函数简单代码示例
2018/01/09 Python
Django处理文件上传File Uploads的实例
2018/05/28 Python
python实现自动网页截图并裁剪图片
2018/07/30 Python
python实现简单图书管理系统
2019/11/22 Python
python 实现从高分辨图像上抠取图像块
2020/01/02 Python
pytorch AvgPool2d函数使用详解
2020/01/03 Python
带你彻底搞懂python操作mysql数据库(cursor游标讲解)
2020/01/06 Python
python进行二次方程式计算的实例讲解
2020/12/06 Python
详解appium自动化测试工具(monitor、uiautomatorviewer)
2021/01/27 Python
美国在线工具商店:Acme Tools
2018/06/26 全球购物
香港万宁官方海外旗舰店:香港健与美连锁店
2018/09/27 全球购物
ECCO俄罗斯官网:北欧丹麦鞋履及皮具品牌
2020/06/26 全球购物
技能比赛获奖感言
2014/02/14 职场文书
优秀语文教师事迹
2014/05/18 职场文书
群众路线领导干部个人对照检查材料(集锦)
2014/09/23 职场文书
体育运动会广播稿
2014/10/05 职场文书
2014年大学生工作总结
2014/11/20 职场文书
安全教育观后感
2015/06/17 职场文书
干部考核工作总结2015
2015/07/24 职场文书
小学课改工作总结
2015/08/13 职场文书