37371 2016-09-18 20:12:23 5053次浏览 4条评论 21 7 0

第一次在Yii论坛上分享自己的代码,请大家多多关照。
下面我分享一个在平时做项目的时候封装的类。这个类专门用来处理二维无限分类数组(比如省市的列表,有id和pid两个属性,其中pid是父分类的id)。各个成员函数的用途已经在注释里面做了详细的说明。

<?php

/**
 * 无限极分类-二维无限分类数组处理类
 **/

class Category 
{
    //无限分类数组,其中必须要有id和pid
    public static $list = [];
    //id => pid 数组
    private static $_sp_list = [];
    //子分类key
    private static $_sk;
    //父分类key
    private static $_pk;

    /**
     *对数组进行初始化处理
     * $cat_list 无限分类数组
     * $skey 数组中子分类的key值
     * $pkey 数组中父分类的key值
     * @return mixed array
     **/
    public function __construct($cat_list, $skey = 'id', $pkey = 'pid')
    {
        parent::init();
        self::$_sk = $skey;
        self::$_pk = $pkey;
        $this->init($cat_list);
    }

    /**
     *对数组进行初始化处理
     * @return mixed array
     **/
    public function init($cat_list)
    {
        if (empty($cat_list))
        {
            return false;
        }
        //对数组进行预处理
        foreach ($cat_list as $key => $val)
        {
            //生成sid => pid 数组
            self::$_sp_list[$val[self::$_sk]] = $val[self::$_pk];
            //以数组的子分类值作为索引
            self::$list[$val[self::$_sk]] = $val;
        }
        unset($cat_list);
    }

    /**
     * 获取格式化的树形数据
     * @param $pid int $list中顶级分类id
     * @param $level int $list中顶级分类的层级
     * @param $html string 上下层级之间的标示符号
     * @return mixed
     **/
    public static function sort($pid = 0, $level = 0, $html = '-')
    {
        if (empty(self::$list))
        {
            return false;
        }
        static $tree = array();
        foreach (self::$list as $v)
        {
            if ($v[self::$_pk] == $pid)
            {
                $v['sort'] = $level + 1;
                $v['html'] = str_repeat($html, $level);
                $tree[$v[self::$_sk]] = $v;
                self::sort($v[self::$_sk], $level + 1);
            }
        }
        return $tree;
    }

    /**
     * 获取分类的无限极子分类,以树型结构显示
     * @param $son string 子节点节点名
     * @return mixed
     **/
    public static function tree($son = 'son')
    {
        if (empty(self::$list))
        {
            return false;
        }
        $list = self::$list;
        foreach ($list as $item)
        {
            $list[$item[self::$_pk]][$son][$item[self::$_sk]] = &$list[$item[self::$_sk]];
        }
        return isset($list[0][$son]) ? $list[0][$son] : array();
    }

    /**
     * 获取分类的祖先分类
     * @param $id int 分类id
     * @param $type bool true-返回祖先分类数组 false-返回祖先分类id
     * @return mixed
     **/
    public static function ancestor($id, $type = true)
    {
        if (empty(self::$list) || empty(self::$_sp_list))
        {
            return false;
        }
        while (self::$_sp_list[$id])
        {
            $id = self::$_sp_list[$id];
        }
        return $type && isset(self::$list[$id]) ? self::$list[$id] : $id;
    }

    /**
     * 获取所有父级分类对应层级关系
     * @param $id int 分类id
     * @param $type bool true-返回分类数组 false-返回分类id
     * @return mixed
     **/
    public static function parents($id, $type = true)
    {
        if (empty(self::$list))
        {
            return false;
        }
        $info = [];
        while (isset(self::$_sp_list[$id]))
        {
            $info[] = $type ? self::$list[$id] : $id;
            $id = self::$_sp_list[$id];
        }
        return $info;
    }

    /**
     * 获取所有子级分类对应层级关系
     * @param $id int 子分类id
     * @param $type bool true-返回分类数组 false-返回分类id
     * @return mixed
     **/
    public static function sons($id, $type = true)
    {
        if (empty(self::$list))
        {
            return false;
        }
        static $info = [];
        foreach (self::$list as $val)
        {
            if ($val[self::$_pk] == $id)
            {
                $info[$val[self::$_sk]] = $type ? $val : $val[self::$_sk];
                if (self::has_son($val[self::$_sk]))
                {
                    self::sons($val[self::$_sk], $type);
                }
            }
        }
        return $info;
    }

    /**
     * 获取所有儿子分类
     * @param $p_id int 父id
     * @param $type bool true-返回分类数组 false-返回分类id
     * @return mixed
     **/
    public static function son($p_id = 0, $type = true)
    {
        if (empty(self::$list))
        {
            return false;
        }
        $_arr = [];
        foreach (self::$list as $val)
        {
            if ($val[self::$_pk] == $p_id)
            {
                $_arr[$val[self::$_sk]] = $type ? $val : $val[self::$_sk];
            }
        }
        return $_arr;
    }

    /**
     * 是否含有子分类,是否是叶子节点
     * @param $pid int 父分类id
     * @return mixed
     **/
    public static function has_son($pid)
    {
        if (empty(self::$list) || empty(self::$_sp_list))
        {
            return false;
        }
        return in_array($pid, array_values(self::$_sp_list));
    }
}


获取省市关系举例:
假如省市关系以无限级的二维形式存与数据库中,

$list = Array
		(
		    [1] => Array
		        (
		            [id] => 1
		            [pid] => 0
		            [name] => 北京市京市市2] => Array
		        (
		            [id] => 2
		            [pid] => 0
		            [name] => 上海市海市市5] => Array
		        (
		            [id] => 5
		            [pid] => 0
		            [name] => 河北省北省省44] => Array
		        (
		            [id] => 44
		            [pid] => 5
		            [name] => 廊坊市坊市市45] => Array
		        (
		            [id] => 45
		            [pid] => 5
		            [name] => 衡水市水市市

可以将这个数组取出放在缓存当中,每次获取时从缓存获取。获取后首先初始化:

$cat = new Category($list);

1.获取省市树形结构数据

$_city_tree = $cat::tree();结果为果为为
Array
(
    [1] => Array
        (
            [id] => 1
            [pid] => 0
            [name] => 北京市京市市son] => Array
                (
                    [415] => Array
                        (
                            [id] => 415
                            [pid] => 1
                            [name] => 北京市京市市5] => Array
        (
            [id] => 5
            [pid] => 0
            [name] => 河北省北省省son] => Array
                (
                    ....

                    [44] => Array
                        (
                            [id] => 44
                            [pid] => 5
                            [name] => 廊坊市坊市市45] => Array
                        (
                            [id] => 45
                            [pid] => 5
                            [name] => 衡水市水市市

2.获取可以直接用于显示的格式化的数据:

$_city_html = $cat::sort(0, 0, '--');结果为果为为
Array
(
    [1] => Array
        (
            [id] => 1
            [pid] => 0
            [name] => 北京市京市市sort] => 1
            [html] => 
        )

    [415] => Array
        (
            [id] => 415
            [pid] => 1
            [name] => 北京市京市市sort] => 2
            [html] => -
        )

    ....

    [5] => Array
        (
            [id] => 5
            [pid] => 0
            [name] => 河北省北省省sort] => 1
            [html] => 
        )

    ....

    [44] => Array
        (
            [id] => 44
            [pid] => 5
            [name] => 廊坊市坊市市sort] => 2
            [html] => -
        )

    [45] => Array
        (
            [id] => 45
            [pid] => 5
            [name] => 衡水市水市市sort] => 2
            [html] => -
        )
    ....
}

这个类在使用时,还需需要加上命名空间,如果想要绑定事件,还要继承\yii\base\Component。
欢迎大家对这个类做有益的补充~~

觉得很赞
亿速云
  • 评论于 2016-09-19 11:26 举报

    谢谢......

    1 条回复
    评论于 2016-09-19 14:57 回复

    多多交流,一起进步~~

  • 评论于 2016-09-23 15:41 举报
    function genTree($items) {
        foreach ($items as $item){
            $items[$item['pid']]['son'][$item['id']] = &$items[$item['id']];
        }
    
        return isset($items[0]['son']) ? $items[0]['son'] : array();
    }
    

    简单的实现

    2 条回复
    评论于 2016-09-23 17:01 回复

    是的额,这个实现非常的简洁,高效!

    评论于 2017-01-12 15:27 回复

    太酷了!!!!!EXCITE!!!!

    , 觉得很赞
  • 评论于 2017-04-02 16:46 举报
    public static function getRegionCode($code){
            $data = self::find()->all();
            $data = ArrayHelper::map($data, 'id','superID');
            $data=self::findOne($data[$code]);
            return  $data['name'];
    
    }
    
    public static function getRegion($id){
            $data = self::find()->all();
            $data = ArrayHelper::map($data, 'id','name');
            return  $data[$id];
    
    }
    
  • 评论于 2019-10-17 17:38 举报

    看着静态属性,静态方法有些别扭,我替换掉了;

    <?php
    
    /**
     * 无限极分类-二维无限分类数组处理类
     *
     **/
    class MultiCat
    {
        //无限分类数组,其中必须要有id和pid
        public $list = [];
        //id => pid 数组
        private $_sp_list = [];
        //子分类key
        private $_sk;
        //父分类key
        private $_pk;
    
        /**
         *对数组进行初始化处理
         * $cat_list 无限分类数组
         * $skey 数组中子分类的key值
         * $pkey 数组中父分类的key值
         * @return mixed array
         **/
        public function __construct($cat_list, $skey = 'id', $pkey = 'pid')
        {
            //parent::init();
            $this->_sk = $skey;
            $this->_pk = $pkey;
            $this->init($cat_list);
        }
    
        /**
         *对数组进行初始化处理
         * @return mixed array
         **/
        public function init($cat_list)
        {
            if (empty($cat_list)) {
                return false;
            }
            //对数组进行预处理
            foreach ($cat_list as $key => $val) {
                //生成sid => pid 数组
                $this->_sp_list[$val[$this->_sk]] = $val[$this->_pk];
                //以数组的子分类值作为索引
                $this->list[$val[$this->_sk]] = $val;
            }
            unset($cat_list);
        }
    
        /**
         * 获取格式化的树形数据
         * @param $pid int $list中顶级分类id
         * @param $level int $list中顶级分类的层级
         * @param $html string 上下层级之间的标示符号
         * @return mixed
         **/
        public function sort($pid = 0, $level = 0, $html = '-')
        {
            if (empty($this->list)) {
                return false;
            }
            static $tree = array();
            foreach ($this->list as $v) {
                if ($v[$this->_pk] == $pid) {
                    $v['sort'] = $level + 1;
                    $v['html'] = str_repeat($html, $level);
                    $tree[$v[$this->_sk]] = $v;
                    $this->sort($v[$this->_sk], $level + 1);
                }
            }
            return $tree;
        }
    
        /**
         * 获取分类的无限极子分类,以树型结构显示
         * @param $son string 子节点节点名
         * @return mixed
         **/
        public function tree($son = 'son')
        {
            if (empty($this->list)) {
                return [];
            }
            $list = $this->list;
            foreach ($list as $item) {
                $list[$item[$this->_pk]][$son][$item[$this->_sk]] = &$list[$item[$this->_sk]];
            }
            return isset($list[0][$son]) ? $list[0][$son] : array();
        }
    
        /**
         * 获取分类的祖先分类
         * @param $id int 分类id
         * @param $type bool true-返回祖先分类数组 false-返回祖先分类id
         * @return mixed
         **/
        public function ancestor($id, $type = true)
        {
            if (empty($this->list) || empty($this->_sp_list)) {
                return false;
            }
            while ($this->_sp_list[$id]) {
                $id = $this->_sp_list[$id];
            }
            return $type && isset($this->list[$id]) ? $this->list[$id] : $id;
        }
    
        /**
         * 获取所有父级分类对应层级关系
         * @param $id int 分类id
         * @param $type bool true-返回分类数组 false-返回分类id
         * @return mixed
         **/
        public function parents($id, $type = true)
        {
            if (empty($this->list)) {
                return false;
            }
            $info = [];
            while (isset($this->_sp_list[$id])) {
                $info[] = $type ? $this->list[$id] : $id;
                $id = $this->_sp_list[$id];
            }
            return $info;
        }
    
        /**
         * 获取所有子级分类对应层级关系
         * @param $id int 子分类id
         * @param $type bool true-返回分类数组 false-返回分类id
         * @return mixed
         **/
        public function sons($id, $type = true)
        {
            if (empty($this->list)) {
                return false;
            }
            static $info = [];
            foreach ($this->list as $val) {
                if ($val[$this->_pk] == $id) {
                    $info[$val[$this->_sk]] = $type ? $val : $val[$this->_sk];
                    if (self::has_son($val[$this->_sk])) {
                        self::sons($val[$this->_sk], $type);
                    }
                }
            }
            return $info;
        }
    
        /**
         * 获取所有儿子分类
         * @param $p_id int 父id
         * @param $type bool true-返回分类数组 false-返回分类id
         * @return mixed
         **/
        public function son($p_id = 0, $type = true)
        {
            if (empty($this->list)) {
                return false;
            }
            $_arr = [];
            foreach ($this->list as $val) {
                if ($val[$this->_pk] == $p_id) {
                    $_arr[$val[$this->_sk]] = $type ? $val : $val[$this->_sk];
                }
            }
            return $_arr;
        }
    
        /**
         * 是否含有子分类,是否是叶子节点
         * @param $pid int 父分类id
         * @return mixed
         **/
        public function has_son($pid)
        {
            if (empty($this->list) || empty($this->_sp_list)) {
                return false;
            }
            return in_array($pid, array_values($this->_sp_list));
        }
    
    }
    

    调用DEMO还是用你的:

     $cat_list = [
                ['id' => 1, 'pid' => 0, 'name' => "北京市",],
                ['id' => 2, 'pid' => 0, 'name' => "上海市",],
                //...
                ['id' => 5, 'pid' => 0, 'name' => "河北省",],
                ['id' => 43, 'pid' => 5, 'name' => "衡水市",],
                ['id' => 44, 'pid' => 5, 'name' => "廊坊市",],
                //...
                ['id' => 100, 'pid' => 44, 'name' => "三河市",],
                ['id' => 101, 'pid' => 44, 'name' => "香河市",],
                ['id' => 133, 'pid' => 100, 'name' => "燕郊镇",],
            ];
            $cat = new MultiCat($cat_list);
            $_city_tree = $cat->tree();
            $_city_html = $cat->sort(0, 0, '-');
            
            VarDumper::dump($_city_tree);
            VarDumper::dump($_city_html);
    
您需要登录后才可以评论。登录 | 立即注册