├── .gitignore ├── src ├── Exceptions │ └── TreeException.php ├── Tree.php ├── Node.php └── Generator.php ├── composer.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /.idea -------------------------------------------------------------------------------- /src/Exceptions/TreeException.php: -------------------------------------------------------------------------------- 1 | tree = collect([]); 26 | } 27 | 28 | /** 29 | * 添加节点 30 | * 31 | * Date: 13/04/2018 32 | * @author George 33 | * @param Node $node 34 | */ 35 | public function addNode(Node $node) 36 | { 37 | $this->tree->push($node); 38 | } 39 | 40 | public function get() 41 | { 42 | return $this->tree; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Node.php: -------------------------------------------------------------------------------- 1 | fill($attributes); 27 | } 28 | 29 | /** 30 | * 添加子节点 31 | * 32 | * Date: 13/04/2018 33 | * @author George 34 | * @param Node $node 35 | * @param string $childrenKey 36 | * 11/06/2020 修改 array_has 函数为 Arr::has 37 | */ 38 | public function addChildren(Node $node, string $childrenKey = 'children') 39 | { 40 | if (Arr::has($this->attributes, $childrenKey)) { 41 | $this->attributes[$childrenKey]->push($node); 42 | } else { 43 | $this->attributes[$childrenKey] = collect([]); 44 | $this->attributes[$childrenKey]->push($node); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Use guide 2 | 3 | ``` 4 | use Betterde\Tree\Generator; 5 | 6 | $menus = [ 7 | [ 8 | 'id' => 1, 9 | 'parent_id' => 0, 10 | 'label' => 'Dashboard', 11 | 'link' => '/dashboard', 12 | 'icon' => null, 13 | 'roles' => 'Admin,' 14 | ], 15 | [ 16 | 'id' => 2, 17 | 'parent_id' => 1, 18 | 'label' => 'Fiance', 19 | 'link' => '/dashboard/finace', 20 | 'icon' => null, 21 | 'roles' => 'Admin,Fiance' 22 | ], 23 | [ 24 | 'id' => 3, 25 | 'parent_id' => 1, 26 | 'label' => 'Operation', 27 | 'link' => '/dashboard/operation', 28 | 'icon' => null, 29 | 'roles' => 'Admin,Operation' 30 | ], 31 | ]; 32 | 33 | $generator = new Generator(); 34 | $tree = $generator->make($menus, 'id', 'parent_id', 'sub_menus', 0); 35 | ``` 36 | # Generated result 37 | ```php 38 | [ 39 | [ 40 | 'id' => 1, 41 | 'parent_id' => 0, 42 | 'label' => 'Dashboard', 43 | 'link' => '/dashboard', 44 | 'icon' => null, 45 | 'roles' => 'Admin,', 46 | 'sub_menus' => [ 47 | [ 48 | 'id' => 2, 49 | 'parent_id' => 1, 50 | 'label' => 'Fiance', 51 | 'link' => '/dashboard/finace', 52 | 'icon' => null, 53 | 'roles' => 'Admin,Fiance' 54 | ], 55 | [ 56 | 'id' => 3, 57 | 'parent_id' => 1, 58 | 'label' => 'Operation', 59 | 'link' => '/dashboard/operation', 60 | 'icon' => null, 61 | 'roles' => 'Admin,Operation' 62 | ] 63 | ] 64 | ] 65 | ]; 66 | ``` 67 | -------------------------------------------------------------------------------- /src/Generator.php: -------------------------------------------------------------------------------- 1 | tree = new Tree(); 60 | } 61 | 62 | 63 | /** 64 | * 生成树结构 65 | * 66 | * Date: 09/04/2018 67 | * @param $collection 68 | * @param string $primaryKey 69 | * @param string $parentKey 70 | * @param string $childrenKey 71 | * @param string $topvalue 72 | * @return Collection|mixed 73 | * @throws TreeException 74 | * @author George 75 | */ 76 | public function make($collection, string $primaryKey = 'id', string $parentKey = 'parent_id', string $childrenKey = 'children', string $topvalue = "") 77 | { 78 | $collection = $this->transform($collection); 79 | 80 | $this->primaryKey = $primaryKey; 81 | $this->childrenKey = $childrenKey; 82 | 83 | $this->collection = $collection->groupBy($parentKey); 84 | 85 | if ($this->addTopNode($topvalue)) { 86 | return $collection; 87 | } 88 | 89 | if (count($this->collection) > 0) { 90 | foreach ($this->tree->get() as $key => $item) { 91 | $this->recursion($item); 92 | } 93 | } 94 | 95 | return $this->tree->get(); 96 | } 97 | 98 | /** 99 | * 添加顶级节点 100 | * 101 | * Date: 13/04/2018 102 | * @author George 103 | * @param $topvalue 104 | * @return bool 105 | * @throws TreeException 106 | */ 107 | public function addTopNode($topvalue) 108 | { 109 | $nodes = $this->collection->pull($topvalue); 110 | 111 | if (empty($nodes)) { 112 | return true; 113 | } 114 | foreach ($nodes as $item) { 115 | $node = new Node($this->isArray($item)); 116 | $this->tree->addNode($node); 117 | } 118 | return false; 119 | } 120 | 121 | /** 122 | * 递归生成树结构 123 | * 124 | * Date: 22/03/2018 125 | * @author George 126 | * @param $item 127 | */ 128 | private function recursion(Node $item) 129 | { 130 | if ($this->collection->has($item->{$this->primaryKey})) { 131 | $this->collection->pull($item->{$this->primaryKey})->map(function ($temp) use ($item) { 132 | $node = new Node($this->isArray($temp)); 133 | $item->addChildren($node, $this->childrenKey); 134 | $this->recursion($node); 135 | }); 136 | } 137 | } 138 | 139 | /** 140 | * 转换数据类型 141 | * 142 | * Date: 09/04/2018 143 | * @author George 144 | * @param $collection 145 | * @return Collection 146 | * @throws TreeException 147 | */ 148 | private function transform($collection) 149 | { 150 | if ($collection instanceof Collection) { 151 | return $collection; 152 | } 153 | 154 | if (is_array($collection)) { 155 | return collect($collection); 156 | } 157 | 158 | throw new TreeException('数据类型错误'); 159 | } 160 | 161 | /** 162 | * Date: 13/04/2018 163 | * @author George 164 | * @param $item 165 | * @return array 166 | * @throws TreeException 167 | */ 168 | public function isArray($item) 169 | { 170 | if (is_array($item)) { 171 | return $item; 172 | } 173 | 174 | if ($item instanceof Model) { 175 | return $item->toArray(); 176 | } 177 | throw new TreeException('数据类型错误'); 178 | } 179 | } 180 | --------------------------------------------------------------------------------