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+DBM的同学录程序(5)
Oct 09 PHP
PHP新手上路(二)
Oct 09 PHP
PHP中获取内网用户MAC地址(WINDOWS/linux)的实现代码
Aug 11 PHP
PHP IF ELSE简化/三元一次式的使用
Aug 22 PHP
具有时效性的php加密解密函数代码
Jun 19 PHP
php curl 获取https请求的2种方法
Apr 27 PHP
php结合安卓客户端实现查询交互实例
May 05 PHP
PHP微信红包API接口
Dec 05 PHP
Paypal实现循环扣款(订阅)功能
Mar 23 PHP
PHP检测接口Traversable用法详解
Dec 29 PHP
PHP5.6读写excel表格文件操作示例
Feb 26 PHP
PHP页面静态化――纯静态与伪静态用法详解
Jun 05 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 随机生成10位字符代码
2009/03/26 PHP
CodeIgniter CLI模式简介
2014/06/17 PHP
PHP生成短网址的3种方法代码实例
2014/07/08 PHP
PHP开发框架Laravel数据库操作方法总结
2014/09/03 PHP
WebGame《逆转裁判》完整版 代码下载(1月24日更新)
2007/01/29 Javascript
jquery ajax 登录验证实现代码
2009/09/23 Javascript
使用CSS和jQuery模拟select并附提交后取得数据的代码
2013/10/18 Javascript
js 判断浏览器使用的语言示例代码
2014/03/22 Javascript
javascript实例分享---具有立体效果的图片特效
2014/06/08 Javascript
用js传递value默认值的示例代码
2014/09/11 Javascript
JavaScript中实现最高效的数组乱序方法
2014/10/11 Javascript
jQuery中noConflict()用法实例分析
2015/02/08 Javascript
nodejs简单实现中英文翻译
2015/05/04 NodeJs
vue-cli3全面配置详解
2018/11/14 Javascript
jQuery zTree树插件的使用教程
2019/08/16 jQuery
微信小程序实现蓝牙打印
2019/09/23 Javascript
vue实现列表拖拽排序的功能
2020/11/02 Javascript
浅谈Django REST Framework限速
2017/12/12 Python
Python学习小技巧总结
2018/06/10 Python
Python实现端口检测的方法
2018/07/24 Python
python使用tornado实现登录和登出
2018/07/28 Python
基于python和flask实现http接口过程解析
2020/06/15 Python
Django serializer优化类视图的实现示例
2020/07/16 Python
animation和transition的区别
2020/10/12 HTML / CSS
Html5实现文件异步上传功能
2017/05/19 HTML / CSS
HTML5 Canvas实现放大镜效果示例
2020/03/25 HTML / CSS
澳大利亚牛仔裤商店:Just Jeans
2016/10/13 全球购物
洲际酒店集团美国官网:IHG美国
2017/11/16 全球购物
英国简约舒适女装品牌:Great Plains
2018/07/27 全球购物
法国春天百货官网:Printemps.com
2020/06/29 全球购物
租车协议书范本
2014/04/22 职场文书
2014小学年度工作总结
2014/12/20 职场文书
党员反腐倡廉学习心得体会
2015/08/15 职场文书
2016年寒假家长评语
2015/10/10 职场文书
python实现Thrift服务端的方法
2021/04/20 Python
Vue 打包后相对路径的引用问题
2022/06/05 Vue.js