php实现的树形结构数据存取类实例


Posted in PHP onNovember 29, 2014

本文实例讲述了php实现的树形结构数据存取类。分享给大家供大家参考。

具体实现代码如下:

<?php 

/** 

 * Tanphp framework 

 * 

 * 

 * @category   Tanphp 

 * @package    Data_structure 

 * @version    $Id: Tree.php 25024 2012-11-26 22:22:22 tanbo $ 

 */ 

 

/** 

 * 树形结构数据存取类 

 *  

 * 用于对树形结构数据进行快速的存取 

 *  

 * @param array $arr 参数必须为标准的二维数组,包含索引字段(id)与表示树形结构的字段(path),如example中所示 

 *  

 * @example <code> 

 * $arr = array( 

 *  array( 'id' => 1, 'name' => 'php', 'path' => '1' ), 

 *  array( 'id' => 3, 'name' => 'php1', 'path' => '1-3' ), 

 *  array( 'id' => 2, 'name' => 'mysql', 'path' => '2' ), 

 *  array( 'id' => 6, 'name' => 'mysql1', 'path' => '2-6' ), 

 *  array( 'id' => 7, 'name' => 'mysql2', 'path' => '2-7' ), 

 *  array( 'id' => 5, 'name' => 'php11', 'path' => '1-3-5' ), 

 *  array( 'id' => 4, 'name' => 'php2', 'path' => '1-4' ), 

 *   ); 

 *  $cate = new Tree($arr); 

 *   

 *  $data = $cate->getChild(2); 

 *   

 *  print_r($data->toArray()); 

 * </code> 

 *  

 */ 

class Tree 

{ 

    public  $_info;                             //节点信息 

    public  $_child = array();                  //子节点 

    private $_parent;                           //父节点 

    private $_data;                             //当前操作的临时数据 

    private static $_indexs         = array();  //所有节点的索引 

    private static $_index_key      = 'id';     //索引键 

    private static $_tree_key       = 'path';   //树形结构表达键 

    private static $_tree_delimiter = '-';      //属性结构表达分割符 

     

    /** 

     * 构造函数 

     *  

     * @param array $arr 

     * @param boole $force_sort 如果为真,将会强制对$arr 进行排序 

     * @return void 

     */ 

    public function __construct(array $arr = array(),  $force_sort=true) 

    { 

        if ($force_sort === true) { 

            $arr=$this->_array_sort($arr, self::$_tree_key); 

        } 

        if (!emptyempty($arr)) { 

            $this->_init($arr); 

        } 

    } 

     

    /** 

     * 初始存储树形数据 

     *  

     * @param array $arr 

     * @return void 

     */ 

    private function _init(array $arr) 

    { 

        foreach ($arr as $item) { 

            $path        = $item[self::$_tree_key]; 

            $paths       = explode(self::$_tree_delimiter, $path); 

            $count_paths = count($paths); 

            $parent_id   = isset($paths[$count_paths-2]) ? $paths[$count_paths-2] : NULL; 

             

            if (   $count_paths>1                                   //如果有父级 

                && array_key_exists($parent_id, self::$_indexs)      //父级已经被存入索引 

                && self::$_indexs[$parent_id] instanceof Tree    //父级为Tree对象 

            ) { 

                self::$_indexs[$parent_id]->addChild($item); 

            } elseif ($count_paths == 1) { 

                $this->addChild($item); 

            } else { 

                throw new Exception("path数据错误".var_export($item, true)); 

            } 

        } 

         

        //print_r(self::$_indexs); 

    } 

     

    /** 

     * 添加子节点 

     *  

     * @param array $item 

     * @return void 

     */ 

    public function addChild(array $item, $parent = NULL) 

    { 

        $child          = new Tree(); 

        $child->_info   = $item; 

        $child->_parent = $parent == NULL ? $this : $parent; 

        $child->_parent->_child[] =  $child; 

         

        $this->_addIndex($item, $child->_getSelf());  

    } 

     

    /** 

     * 添加节点到索引 

     *  

     * @param array $item 

     * @param mix $value 

     * @return void 

     */ 

    private function _addIndex(array $item, $value) 

    { 

        if (array_key_exists(self::$_index_key, $item) && is_int($item[self::$_index_key])) { 

            self::$_indexs[$item[self::$_index_key]] = $value; 

        } else { 

            throw new Exception("id字段不存在或者不为字符串"); 

        } 

    } 

     

    /** 

     * 获取对自己的引用 

     *  

     * @return Tree object quote 

     */ 

    private function _getSelf() 

    { 

        return $this; 

    } 

     

    /** 

     * 获取指定id的节点的子节点 

     *  

     * @param int $id 

     * @return Tree object 

     */ 

    public function getChild($id) 

    { 

        $data       = self::$_indexs[$id]->_child; 

        $this->_data = $data; 

        return $this; 

    } 

     

    /** 

     * 获取指定id的节点的父节点 

     *  

     * @param int $id 

     * @return Tree object 

     */ 

    public function getParent($id) 

    { 

        $data = self::$_indexs[$id]->_parent; 

        $this->_data = $data; 

        return $this; 

    } 

     

    /** 

     * 获取指定id的节点的同级节点 

     * 

     * @param int $id 

     * @return Tree object 

     */ 

    public function getBrother($id) 

    { 

        $data = self::$_indexs[$id]->_parent->_child; 

        $this->_data = $data; 

        return $this; 

    } 

     

    /** 

     * 将Tree对象转化为数组 

     *  

     * @param  object $object 

     * @return array 

     */ 

     public function toArray($obj = NULL) 

     { 

        $obj  = ($obj === NULL) ? $this->_data : $obj; 

        $arr  = array(); 

        $_arr = is_object($obj) ? $this->_getBaseInfo($obj) : $obj; 

         

        if (is_array($_arr)) { 

            foreach ($_arr as $key => $val){ 

                 

                $val = (is_array($val) || is_object($val)) ? $this->toArray($val) : $val;

                $arr[$key] = $val; 

            } 

        } else { 

            throw new Exception("_arr不是数组"); 

        } 

      

        return $arr; 

    } 

     

    /** 

     * 过滤_parent等字段,以免造成无限循环 

     *  

     * @param object $obj 

     * @return void 

     */ 

    private function _getBaseInfo($obj) 

    { 

        $vars = get_object_vars($obj); 

        $baseInfo['_info']  =  $vars['_info']; 

        $baseInfo['_child'] =  $vars['_child']; 

        return $baseInfo; 

    } 

     

    /** 

     * 二维数组排序 

     * 

     * 根据指定的键名对二维数组进行升序或者降序排列 

     * 

     * @param array  $arr 二维数组 

     * @param string $keys 

     * @param string $type 必须为 asc或desc 

     * @throws 当参数非法时抛出异常 

     * @return 返回排序好的数组 

     */ 

    private function _array_sort(array $arr, $keys, $type = 'asc') { 

        if (!is_string($keys)) { 

            throw new Exception("非法参数keys:参数keys的类型必须为字符串"); 

        } 

     

        $keysvalue = $new_array = array(); 

        foreach ($arr as $k=>$v) { 

            if (!is_array($v) || !isset($v[$keys])) { 

                throw new Exception("参数arr不是二维数组或arr子元素中不存在键'{$keys}'"); 

            } 

            $keysvalue[$k] = $v[$keys]; 

        } 

     

        switch ($type) { 

            case 'asc': 

                asort($keysvalue); 

                break; 

            case 'desc': 

                arsort($keysvalue); 

                break; 

            default: 

                throw new Exception("非法参数type :参数type的值必须为 'asc' 或 'desc'"); 

        } 

     

        reset($keysvalue); 

        foreach ($keysvalue as $k=>$v) { 

            $new_array[$k] = $arr[$k]; 

        } 

        return $new_array; 

    } 

} 

?>

希望本文所述对大家的PHP程序设计有所帮助。

PHP 相关文章推荐
PHP 和 COM
Oct 09 PHP
php出现Cannot modify header information问题的解决方法大全
Apr 09 PHP
PHP屏蔽蜘蛛访问代码及常用搜索引擎的HTTP_USER_AGENT
Mar 06 PHP
php 下载保存文件保存到本地的两种实现方法
Aug 12 PHP
CMS中PHP判断系统是否已经安装的方法示例
Jul 26 PHP
PHP微信支付实例解析
Jul 22 PHP
总结PHP如何获取当前主机、域名、网址、路径、端口和参数等
Sep 09 PHP
PHP中常用的魔术方法
Apr 28 PHP
windows下的WAMP环境搭建图文教程(推荐)
Jul 27 PHP
PHP7扩展开发教程之Hello World实现方法示例
Aug 03 PHP
定位地理位置PHP判断员工打卡签到经纬度是否在打卡之内
May 23 PHP
Laravel框架Eloquent ORM修改数据操作示例
Dec 03 PHP
Codeigniter购物车类不能添加中文的解决方法
Nov 29 #PHP
ThinkPHP模版中导入CSS和JS文件的方法
Nov 29 #PHP
ThinkPHP中Session用法详解
Nov 29 #PHP
thinkphp的静态缓存用法分析
Nov 29 #PHP
thinkphp中memcache的用法实例
Nov 29 #PHP
thinkPHP实现瀑布流的方法
Nov 29 #PHP
php删除左端与右端空格的方法
Nov 29 #PHP
You might like
PHP循环语句笔记(foreach,list)
2011/11/29 PHP
PHP SPL标准库之SplFixedArray使用实例
2015/05/12 PHP
UTF-8正则表达式如何匹配汉字
2015/08/03 PHP
向fckeditor编辑器插入指定代码的方法
2007/05/25 Javascript
JavaScript 异步调用框架 (Part 6 - 实例 &amp; 模式)
2009/08/04 Javascript
JavaScript中的prototype使用说明
2010/04/13 Javascript
Javascript异步表单提交,图片上传,兼容异步模拟ajax技术
2010/05/10 Javascript
js下关于onmouseout、事件冒泡的问题经验小结
2010/12/09 Javascript
JavaScript通过RegExp实现客户端验证处理程序
2013/05/07 Javascript
js限制文本框只能输入中文的方法
2015/08/11 Javascript
js+canvas绘制矩形的方法
2016/01/28 Javascript
一次$.getJSON不执行的简单记录
2016/07/19 Javascript
浅析Node.js实现HTTP文件下载
2016/08/05 Javascript
BootStrap 图片样式、辅助类样式和CSS组件的实例详解
2017/01/20 Javascript
详解vue-router和vue-cli以及组件之间的传值
2017/07/04 Javascript
微信小程序基于slider组件动态修改标签透明度的方法示例
2017/12/04 Javascript
vue axios 简单封装以及思考
2018/10/09 Javascript
详解钉钉小程序组件之自定义模态框(弹窗封装实现)
2020/03/07 Javascript
JS+CSS+HTML实现“代码雨”类似黑客帝国文字下落效果
2020/03/17 Javascript
点球小游戏python脚本
2018/05/22 Python
删除python pandas.DataFrame 的多重index实例
2018/06/08 Python
Python3实现将本地JSON大数据文件写入MySQL数据库的方法
2018/06/13 Python
使用python获取(宜宾市地震信息)地震信息
2019/06/20 Python
关于Flask项目无法使用公网IP访问的解决方式
2019/11/19 Python
浅谈Python xlwings 读取Excel文件的正确姿势
2021/02/26 Python
简述DNS进行域名解析的过程
2013/12/02 面试题
人事部专员岗位职责
2014/03/04 职场文书
洗发露广告词
2014/03/14 职场文书
五年级学生评语
2014/04/22 职场文书
中学生教师节演讲稿
2014/09/03 职场文书
保密工作整改报告
2014/11/06 职场文书
2014年职称评定工作总结
2014/11/26 职场文书
大一学生个人总结
2015/02/15 职场文书
python实现高效的遗传算法
2021/04/07 Python
Java面试题冲刺第十五天--设计模式
2021/08/07 面试题
详解Spring Security如何在权限中使用通配符
2022/06/28 Java/Android