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 相关文章推荐
实用函数4
Nov 08 PHP
phpinfo 系统查看参数函数代码
Jun 05 PHP
解析php中获取系统信息的方法
Jun 25 PHP
PHP采集类Snoopy抓取图片实例
Jun 19 PHP
php生成百度sitemap站点地图类函数实例
Oct 17 PHP
PHP7.0安装笔记整理
Aug 28 PHP
如何使用PHP对网站验证码进行破解
Sep 17 PHP
php根据日期或时间戳获取星座信息和生肖等信息
Oct 20 PHP
PHP接收json 并将接收数据插入数据库的实现代码
Dec 01 PHP
YII Framework框架教程之国际化实现方法
Mar 14 PHP
ThinkPHP连接Oracle数据库
Apr 22 PHP
Laravel中Kafka的使用详解
Mar 24 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 注释规范
2012/03/29 PHP
基于php导出到Excel或CSV的详解(附utf8、gbk 编码转换)
2013/06/25 PHP
php实现文件下载实例分享
2014/06/02 PHP
php以post形式发送xml的方法
2014/11/04 PHP
php开发最强大的IDE编辑的phpstorm 2020.2配置Xdebug调试的详细教程
2020/08/17 PHP
addRule在firefox下的兼容写法
2006/11/30 Javascript
javascript 客户端验证上传图片的大小(兼容IE和火狐)
2009/08/15 Javascript
formStorage 基于jquery的一个插件(存储表单中元素的状态到本地)
2012/01/20 Javascript
jQuery图片轮播的具体实现
2013/09/11 Javascript
js 动态为textbox添加下拉框数据源的方法
2014/04/24 Javascript
javascript操作excel生成报表示例
2014/05/08 Javascript
jQuery中:disabled选择器用法实例
2015/01/04 Javascript
封装好的js判断操作系统与浏览器代码分享
2015/01/09 Javascript
JavaScript+html5 canvas绘制的小人效果
2016/01/27 Javascript
ES6 javascript中Class类继承用法实例详解
2017/10/30 Javascript
微信小程序 函数防抖 解决重复点击消耗性能问题实现代码
2019/09/12 Javascript
layui自己添加图片按钮并点击跳转页面的例子
2019/09/14 Javascript
React Hooks 实现和由来以及解决的问题详解
2020/01/17 Javascript
python和shell变量互相传递的几种方法
2013/11/20 Python
Python中的lstrip()方法使用简介
2015/05/19 Python
简述:我为什么选择Python而不是Matlab和R语言
2017/11/14 Python
100行Python代码实现自动抢火车票(附源码)
2018/01/11 Python
python监测当前联网状态并连接的实例
2018/12/18 Python
Python命令行参数定义及需要注意的地方
2020/11/30 Python
耐克巴西官方网站:Nike巴西
2016/08/14 全球购物
法国在线药房:DoctiPharma
2020/10/21 全球购物
深圳-东方伟业笔试部分
2015/02/11 面试题
留学自荐信的技巧
2013/10/17 职场文书
酒店中秋节活动方案
2014/01/31 职场文书
大课间体育活动方案
2014/03/12 职场文书
环境科学专业教师求职信
2014/07/12 职场文书
党员个人公开承诺书
2014/08/29 职场文书
工作批评与自我批评范文
2014/10/16 职场文书
超市采购员岗位职责
2015/04/07 职场文书
六种css3实现的边框过渡效果
2021/04/22 HTML / CSS
如何使用python包中的sched事件调度器
2022/04/30 Python