首页 php教程 php手册 php树形结构数据存取实例类

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

May 25, 2016 pm 04:54 PM
explode foreach

本文章来给大家分享一款不错的树形结构的php类代码,各位朋友可参考。
 代码如下 复制代码


/**
 * Tanphp framework
 *
 *
 * @category   Tanphp
 * @package    Data_structure
 * @copyright  Copyright (c) 2012 谭博  tanbo.name
 * @version    $Id: Tree.php 25024 2012-11-26 22:22:22 tanbo $
 */


/**
 * 树形结构数据存取类
 *
 * 用于对树形结构数据进行快速的存取
 *
 * @param array $arr 参数必须为标准的二维数组,包含索引字段(id)与表示树形结构的字段(path),如example中所示
 *
 * @example <br> * $arr = array(<br> *  array( 'id' => 1, 'name' => 'php', 'path' => '1' ),<br> *  array( 'id' => 3, 'name' => 'php1', 'path' => '1-3' ),<br> *  array( 'id' => 2, 'name' => 'mysql', 'path' => '2' ),<br> *  array( 'id' => 6, 'name' => 'mysql1', 'path' => '2-6' ),<br> *  array( 'id' => 7, 'name' => 'mysql2', 'path' => '2-7' ),<br> *  array( 'id' => 5, 'name' => 'php11', 'path' => '1-3-5' ),<br> *  array( 'id' => 4, 'name' => 'php2', 'path' => '1-4' ),<br> *   );<br> *  $cate = new Tree($arr);<br> * <br> *  $data = $cate->getChild(2);<br> * <br> *  print_r($data->toArray());<br> *
 *
 */

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 (!empty($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;
    }
   
}

?>



教程地址:

欢迎转载!但请带上文章地址^^

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
威尔R.E.P.O.有交叉游戏吗?
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Java ArrayList遍历时使用foreach和iterator删除元素的区别是什么? Java ArrayList遍历时使用foreach和iterator删除元素的区别是什么? Apr 27, 2023 pm 03:40 PM

一、Iterator和foreach的区别多态差别(foreach底层就是Iterator)Iterator是一个接口类型,他不关心集合或者数组的类型;for和foreach都需要先知道集合的类型,甚至是集合内元素的类型;1.为啥说foreach底层就是Iterator编写的代码:反编译代码:二、foreach与iterator时remove的区别先来看阿里java开发手册但1的时候不会报错,2的时候就会报错(java.util.ConcurrentModificationException)首

php如何判断foreach循环到第几个 php如何判断foreach循环到第几个 Jul 10, 2023 pm 02:18 PM

​php判断foreach循环到第几个的步骤:1、创建一个“$fruits”的数组;2、创建一个计数器变量“$counter”初始值为0;3、使用“foreach”循环遍历数组,并在循环体中增加计数器变量的值,再输出每个元素和它们的索引;4、在“foreach”循环体外输出计数器变量的值,以确认循环到了第几个元素。

PHP返回一个键值翻转后的数组 PHP返回一个键值翻转后的数组 Mar 21, 2024 pm 02:10 PM

这篇文章将为大家详细讲解有关PHP返回一个键值翻转后的数组,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。PHP键值翻转数组键值翻转是一种对数组进行的操作,它将数组中的键和值进行交换,生成一个新的数组,其中原始键作为值,原始值作为键。实现方法在php中,可以通过以下方法对数组进行键值翻转:array_flip()函数:array_flip()函数专门用于键值翻转操作。它接收一个数组作为参数,并返回一个新的数组,其中键和值已交换。$original_array=[

PHP explode函数使用方法与报错解决 PHP explode函数使用方法与报错解决 Mar 10, 2024 am 09:18 AM

PHP中的explode函数是一种用来将字符串分割成数组的函数,它非常常用且灵活。在使用explode函数的过程中,常常会遇到一些报错和问题,本文将介绍explode函数的基本用法并提供一些解决报错的方法。一、explode函数基本用法在PHP中,explode函数的基本语法如下:explode(string$separator,string$stri

PHP中使用explode函数时常见的错误及解决方案 PHP中使用explode函数时常见的错误及解决方案 Mar 11, 2024 am 08:33 AM

标题:PHP中使用explode函数时常见的错误及解决方案在PHP中,explode函数是用于将字符串分割成数组的常用函数。然而,由于使用不当或者数据格式不正确,可能会导致一些常见的错误。本文将针对在使用explode函数时可能遇到的问题进行分析,并提供解决方案和具体的代码示例。错误一:未传入分隔符参数在使用explode函数时,最常见的错误之一是未传入分隔

PHP返回数组中的当前元素 PHP返回数组中的当前元素 Mar 21, 2024 pm 12:36 PM

这篇文章将为大家详细讲解有关PHP返回数组中的当前元素,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。获取PHP数组中的当前元素php为访问和操作数组提供了多种方法,其中包括获取数组中的当前元素。以下介绍几种常用的技术:1.current()函数current()函数返回数组内部指针当前指向的元素。指针最初指向数组的第一个元素。使用以下语法:$currentElement=current($array);2.key()函数key()函数返回数组内部指针当前指向元

使用explode和implode函数分割和合并字符串 使用explode和implode函数分割和合并字符串 Jun 15, 2023 pm 08:42 PM

在PHP编程中,处理字符串是一个经常需要进行的操作。其中,分割和合并字符串则是两种常见的需求。为了更方便地进行这些操作,PHP提供了两个非常实用的函数,即explode和implode函数。本文将介绍这两个函数的用法,以及一些实用的技巧。一、explode函数explode函数用于将一个字符串按照指定的分隔符进行分割,并返回一个数组。其函数原型如下:arra

foreach和for循环的区别是什么 foreach和for循环的区别是什么 Jan 05, 2023 pm 04:26 PM

区别:1、for通过索引来循环遍历每一个数据元素,而forEach通过JS底层程序来循环遍历数组的数据元素;2、for可以通过break关键词来终止循环的执行,而forEach不可以;3、for可以通过控制循环变量的数值来控制循环的执行,而forEach不行;4、for在循环外可以调用循环变量,而forEach在循环外不能调用循环变量;5、for的执行效率要高于forEach。

See all articles