| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 | 
							- <?php
 
- namespace app\common;
 
- class Tree
 
- {
 
-     /**
 
-      * 获取完整的树结构,包含祖先节点
 
-      */
 
-     const INCLUDE_ANCESTORS = 1;
 
-     /**
 
-      * 获取部分树,不包含祖先节点
 
-      */
 
-     const EXCLUDE_ANCESTORS = 0;
 
-     /**
 
-      * 数据
 
-      * @var array
 
-      */
 
-     protected $data = [];
 
-     /**
 
-      * 哈希树
 
-      * @var array
 
-      */
 
-     protected $hashTree = [];
 
-     /**
 
-      * 父级字段名
 
-      * @var string
 
-      */
 
-     protected $pidName = 'pid';
 
-     /**
 
-      * @param $data
 
-      * @param string $pid_name
 
-      */
 
-     public function __construct($data, string $pid_name = 'pid')
 
-     {
 
-         $this->pidName = $pid_name;
 
-         if (is_object($data) && method_exists($data, 'toArray')) {
 
-             $this->data = $data->toArray();
 
-         } else {
 
-             $this->data = (array)$data;
 
-             $this->data = array_map(function ($item) {
 
-                 if (is_object($item) && method_exists($item, 'toArray')) {
 
-                     return $item->toArray();
 
-                 }
 
-                 return $item;
 
-             }, $this->data);
 
-         }
 
-         $this->hashTree = $this->getHashTree();
 
-     }
 
-     /**
 
-      * 获取子孙节点
 
-      * @param array $include
 
-      * @param bool $with_self
 
-      * @return array
 
-      */
 
-     public function getDescendant(array $include, bool $with_self = false): array
 
-     {
 
-         $items = [];
 
-         foreach ($include as $id) {
 
-             if (!isset($this->hashTree[$id])) {
 
-                 return [];
 
-             }
 
-             if ($with_self) {
 
-                 $item = $this->hashTree[$id];
 
-                 unset($item['children']);
 
-                 $items[$item['id']] = $item;
 
-             }
 
-             foreach ($this->hashTree[$id]['children'] ?? [] as $item) {
 
-                 unset($item['children']);
 
-                 $items[$item['id']] = $item;
 
-                 foreach ($this->getDescendant([$item['id']]) as $it) {
 
-                     $items[$it['id']] = $it;
 
-                 }
 
-             }
 
-         }
 
-         return array_values($items);
 
-     }
 
-     /**
 
-      * 获取哈希树
 
-      * @param array $data
 
-      * @return array
 
-      */
 
-     protected function getHashTree(array $data = []): array
 
-     {
 
-         $data = $data ?: $this->data;
 
-         $hash_tree = [];
 
-         foreach ($data as $item) {
 
-             $hash_tree[$item['id']] = $item;
 
-         }
 
-         foreach ($hash_tree as $index => $item) {
 
-             if ($item[$this->pidName] && isset($hash_tree[$item[$this->pidName]])) {
 
-                 $hash_tree[$item[$this->pidName]]['children'][$hash_tree[$index]['id']] = &$hash_tree[$index];
 
-             }
 
-         }
 
-         return $hash_tree;
 
-     }
 
-     /**
 
-      * 获取树
 
-      * @param array $include
 
-      * @param int $type
 
-      * @return array|null
 
-      */
 
-     public function getTree(array $include = [], int $type = 1): ?array
 
-     {
 
-         // $type === static::EXCLUDE_ANCESTORS
 
-         if ($type === static::EXCLUDE_ANCESTORS) {
 
-             $items = [];
 
-             $include = array_unique($include);
 
-             foreach ($include as $id) {
 
-                 if (!isset($this->hashTree[$id])) {
 
-                     return [];
 
-                 }
 
-                 $items[] = $this->hashTree[$id];
 
-             }
 
-             return static::arrayValues($items);
 
-         }
 
-         // $type === static::INCLUDE_ANCESTORS
 
-         $hash_tree = $this->hashTree;
 
-         $items = [];
 
-         if ($include) {
 
-             $map = [];
 
-             foreach ($include as $id) {
 
-                 if (!isset($hash_tree[$id])) {
 
-                     continue;
 
-                 }
 
-                 $item = $hash_tree[$id];
 
-                 $max_depth = 100;
 
-                 while ($max_depth-- > 0 && $item[$this->pidName] && isset($hash_tree[$item[$this->pidName]])) {
 
-                     $last_item = $item;
 
-                     $pid = $item[$this->pidName];
 
-                     $item = $hash_tree[$pid];
 
-                     $item_id = $item['id'];
 
-                     if (empty($map[$item_id])) {
 
-                         $map[$item_id] = 1;
 
-                         $hash_tree[$pid]['children'] = [];
 
-                     }
 
-                     $hash_tree[$pid]['children'][$last_item['id']] = $last_item;
 
-                     $item = $hash_tree[$pid];
 
-                 }
 
-                 $items[$item['id']] = $item;
 
-             }
 
-         } else {
 
-             $items = $hash_tree;
 
-         }
 
-         $formatted_items = [];
 
-         foreach ($items as $item) {
 
-             if (!$item[$this->pidName] || !isset($hash_tree[$item[$this->pidName]])) {
 
-                 $formatted_items[] = $item;
 
-             }
 
-         }
 
-         return static::arrayValues($formatted_items);
 
-     }
 
-     /**
 
-      * 递归重建数组下标
 
-      * @param $array
 
-      * @return array
 
-      */
 
-     public static function arrayValues($array): array
 
-     {
 
-         if (!$array) {
 
-             return [];
 
-         }
 
-         if (!isset($array['children'])) {
 
-             $current = current($array);
 
-             if (!is_array($current)) {
 
-                 return $array;
 
-             }
 
-             $tree = array_values($array);
 
-             foreach ($tree as $index => $item) {
 
-                 $tree[$index] = static::arrayValues($item);
 
-             }
 
-             return $tree;
 
-         }
 
-         $array['children'] = array_values($array['children']);
 
-         foreach ($array['children'] as $index => $child) {
 
-             $array['children'][$index] = static::arrayValues($child);
 
-         }
 
-         return $array;
 
-     }
 
- }
 
 
  |