├── README.md └── function.php /README.md: -------------------------------------------------------------------------------- 1 | # Recursive-And-Cluster-Array 2 | PHP recursive and cluster multi dimentional nested array 3 | ![cluster-schema](http://gorkemduymaz.com/images/cluster.jpg) 4 | ```php 5 | Array 6 | ( 7 | [0] => Array 8 | ( 9 | [id] => 1 10 | [name] => Menu Item 1 11 | [parent_id] => 0 12 | ) 13 | 14 | [1] => Array 15 | ( 16 | [id] => 2 17 | [name] => Menu Item 2 18 | [parent_id] => 0 19 | ) 20 | 21 | [2] => Array 22 | ( 23 | [id] => 3 24 | [name] => Menu Item 3 25 | [parent_id] => 0 26 | ) 27 | 28 | [3] => Array 29 | ( 30 | [id] => 4 31 | [name] => Menu Item 1.1 32 | [parent_id] => 1 33 | ) 34 | 35 | [4] => Array 36 | ( 37 | [id] => 11 38 | [name] => Menu Item 1.2 39 | [parent_id] => 1 40 | ) 41 | 42 | [5] => Array 43 | ( 44 | [id] => 5 45 | [name] => Menu Item 2.1 46 | [parent_id] => 2 47 | ) 48 | 49 | [6] => Array 50 | ( 51 | [id] => 6 52 | [name] => Menu Item 3.1 53 | [parent_id] => 3 54 | ) 55 | 56 | [7] => Array 57 | ( 58 | [id] => 12 59 | [name] => Menu Item 3.2 60 | [parent_id] => 3 61 | ) 62 | 63 | [8] => Array 64 | ( 65 | [id] => 7 66 | [name] => Menu Item 1.1.1 67 | [parent_id] => 4 68 | ) 69 | 70 | [9] => Array 71 | ( 72 | [id] => 9 73 | [name] => Menu Item 2.1.1 74 | [parent_id] => 5 75 | ) 76 | 77 | [10] => Array 78 | ( 79 | [id] => 8 80 | [name] => Menu Item 1.1.1.1 81 | [parent_id] => 7 82 | ) 83 | 84 | [11] => Array 85 | ( 86 | [id] => 10 87 | [name] => Menu Item 1.1.1.1.1 88 | [parent_id] => 8 89 | ) 90 | 91 | [12] => Array 92 | ( 93 | [id] => 14 94 | [name] => Menu Item 2.1.1.1 95 | [parent_id] => 9 96 | ) 97 | 98 | [13] => Array 99 | ( 100 | [id] => 13 101 | [name] => Menu Item 2.1.1.2 102 | [parent_id] => 9 103 | ) 104 | 105 | ) 106 | ``` 107 | 108 | 109 | ```php 110 | $cluster= new ClusterArray(); 111 | print_r($cluster->cluster($elements)); 112 | ``` 113 | 114 | ```php 115 | Array 116 | ( 117 | [0] => Array 118 | ( 119 | [id] => 1 120 | [name] => Menu Item 1 121 | [parent_id] => 0 122 | [lft] => 1 123 | [rgt] => 12 124 | [depht] => 0 125 | [children] => Array 126 | ( 127 | [0] => Array 128 | ( 129 | [id] => 4 130 | [name] => Menu Item 1.1 131 | [parent_id] => 1 132 | [lft] => 2 133 | [rgt] => 9 134 | [depht] => 1 135 | [children] => Array 136 | ( 137 | [0] => Array 138 | ( 139 | [id] => 7 140 | [name] => Menu Item 1.1.1 141 | [parent_id] => 4 142 | [lft] => 3 143 | [rgt] => 8 144 | [depht] => 2 145 | [children] => Array 146 | ( 147 | [0] => Array 148 | ( 149 | [id] => 8 150 | [name] => Menu Item 1.1.1.1 151 | [parent_id] => 7 152 | [lft] => 4 153 | [rgt] => 7 154 | [depht] => 3 155 | [children] => Array 156 | ( 157 | [0] => Array 158 | ( 159 | [id] => 10 160 | [name] => Menu Item 1.1.1.1.1 161 | [parent_id] => 8 162 | [lft] => 5 163 | [rgt] => 6 164 | [depht] => 4 165 | ) 166 | 167 | ) 168 | 169 | ) 170 | 171 | ) 172 | 173 | ) 174 | 175 | ) 176 | 177 | ) 178 | 179 | [1] => Array 180 | ( 181 | [id] => 11 182 | [name] => Menu Item 1.2 183 | [parent_id] => 1 184 | [lft] => 10 185 | [rgt] => 11 186 | [depht] => 1 187 | ) 188 | 189 | ) 190 | 191 | ) 192 | 193 | [1] => Array 194 | ( 195 | [id] => 2 196 | [name] => Menu Item 2 197 | [parent_id] => 0 198 | [lft] => 13 199 | [rgt] => 22 200 | [depht] => 0 201 | [children] => Array 202 | ( 203 | [0] => Array 204 | ( 205 | [id] => 5 206 | [name] => Menu Item 2.1 207 | [parent_id] => 2 208 | [lft] => 14 209 | [rgt] => 21 210 | [depht] => 1 211 | [children] => Array 212 | ( 213 | [0] => Array 214 | ( 215 | [id] => 9 216 | [name] => Menu Item 2.1.1 217 | [parent_id] => 5 218 | [lft] => 15 219 | [rgt] => 20 220 | [depht] => 2 221 | [children] => Array 222 | ( 223 | [0] => Array 224 | ( 225 | [id] => 14 226 | [name] => Menu Item 2.1.1.1 227 | [parent_id] => 9 228 | [lft] => 16 229 | [rgt] => 17 230 | [depht] => 3 231 | ) 232 | 233 | [1] => Array 234 | ( 235 | [id] => 13 236 | [name] => Menu Item 2.1.1.2 237 | [parent_id] => 9 238 | [lft] => 18 239 | [rgt] => 19 240 | [depht] => 3 241 | ) 242 | 243 | ) 244 | 245 | ) 246 | 247 | ) 248 | 249 | ) 250 | 251 | ) 252 | 253 | ) 254 | 255 | [2] => Array 256 | ( 257 | [id] => 3 258 | [name] => Menu Item 3 259 | [parent_id] => 0 260 | [lft] => 23 261 | [rgt] => 28 262 | [depht] => 0 263 | [children] => Array 264 | ( 265 | [0] => Array 266 | ( 267 | [id] => 6 268 | [name] => Menu Item 3.1 269 | [parent_id] => 3 270 | [lft] => 24 271 | [rgt] => 25 272 | [depht] => 1 273 | ) 274 | 275 | [1] => Array 276 | ( 277 | [id] => 12 278 | [name] => Menu Item 3.2 279 | [parent_id] => 3 280 | [lft] => 26 281 | [rgt] => 27 282 | [depht] => 1 283 | ) 284 | 285 | ) 286 | 287 | ) 288 | 289 | ) 290 | ``` 291 | ###### You can save lft,rgt and depth to database so you can easily access child rows with one sql and also you can adjust max and min depth. 292 | 293 | # 294 | # 295 | ```sql 296 | select `id`, `name`, `parent_id`, `lft`, `rgt`, `depth` from `table` where `lft` >= ? and `lft` <= ? and `depth` < ? order by `lft` asc 297 | ``` 298 | ###### Getting between 2 and 8 299 | # 300 | ```php 301 | Array 302 | ( 303 | [0] => Array 304 | ( 305 | [id] => 4 306 | [name] => Menu Item 1.1 307 | [parent_id] => 1 308 | [lft] => 1 309 | [rgt] => 6 310 | [depth] => 0 311 | [children] => Array 312 | ( 313 | [0] => Array 314 | ( 315 | [id] => 7 316 | [name] => Menu Item 1.1.1 317 | [parent_id] => 4 318 | [lft] => 2 319 | [rgt] => 5 320 | [depth] => 1 321 | [children] => Array 322 | ( 323 | [0] => Array 324 | ( 325 | [id] => 8 326 | [name] => Menu Item 1.1.1.1 327 | [parent_id] => 7 328 | [lft] => 3 329 | [rgt] => 4 330 | [depth] => 2 331 | ) 332 | 333 | ) 334 | 335 | ) 336 | 337 | ) 338 | 339 | ) 340 | 341 | [1] => Array 342 | ( 343 | [id] => 11 344 | [name] => Menu Item 1.2 345 | [parent_id] => 1 346 | [lft] => 7 347 | [rgt] => 8 348 | [depth] => 0 349 | ) 350 | 351 | ) 352 | 353 | 354 | ``` 355 | -------------------------------------------------------------------------------- /function.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | class ClusterArray 9 | { 10 | public $table_id = 'parent_id'; 11 | 12 | /** 13 | * Make array recursive and cluster 14 | * 15 | * @param array $elements 16 | * @param int $recursive 17 | * @param int $max 18 | * @param int $depth 19 | * @return array 20 | */ 21 | public function cluster(array $elements, $recursive = 0, $max = 0, $depth = 0) 22 | { 23 | 24 | foreach ($elements as $element) { 25 | if (!isset($parentId)) { 26 | $parentId = $element[$this->table_id]; 27 | } elseif ($element[$this->table_id] < $parentId) { 28 | $parentId = $element[$this->table_id]; 29 | } 30 | } 31 | $cluster = $this->buildTree($elements, $parentId, $max, $depth); 32 | 33 | if ($recursive) { 34 | return $cluster; 35 | } 36 | $cluster = $this->unBuildTree($cluster); 37 | return $cluster; 38 | } 39 | 40 | 41 | /** 42 | * Re-sort array non recursive 43 | * 44 | * @param $elements 45 | * @param array $branch 46 | * @return array 47 | */ 48 | public function unBuildTree($elements, $branch = []) 49 | { 50 | foreach ($elements as $element) { 51 | if (isset($element['children'])) { 52 | 53 | $branch = $this->unBuildTree($element['children'], $branch); 54 | 55 | unset($element['children']); 56 | 57 | } 58 | $branch[] = $element; 59 | } 60 | return $branch; 61 | } 62 | 63 | /** 64 | * Sort array as recursive 65 | * 66 | * @param array $elements 67 | * @param $parentId 68 | * @param int $max 69 | * @param int $depth 70 | * @return array 71 | */ 72 | public function buildTree(array $elements, $parentId, $max = 0, $depth = 0) 73 | { 74 | $branch = array(); 75 | 76 | foreach ($elements as $element) { 77 | 78 | if ($element[$this->table_id] == $parentId) { 79 | 80 | $element['lft'] = $max = $max + 1; 81 | $element['rgt'] = $max + 1; 82 | $element['depth'] = $depth; 83 | $children = $this->buildTree($elements, $element['id'], $max, $depth + 1); 84 | if ($children) { 85 | $element['rgt'] = $max = end($children)['rgt'] + 1; 86 | $element['children'] = $children; 87 | } else { 88 | $element['rgt'] = $max = $max + 1; 89 | } 90 | $branch[] = $element; 91 | } 92 | } 93 | 94 | return $branch; 95 | } 96 | } --------------------------------------------------------------------------------