php - Traversing Hierarchy Tree Adjacency List Model in Yii2 -


i stuck in 1 logic can't understand how done , traverse list.

actually creating category list further used in creating products. wanted category list should in form of parent , sub nodes adjacency list model.

database:

id        categoryname        parent [id foreign key parent]  1                            1  2           b                  2  3           c                  2  4           e                  2  5           f                  3  6           g                  4 

fetching details activequerry in yii2

$rows = category::find() ->asarray() ->all();

$rows array contains data form

array (   [0] => array     (         [id] => 1         [categoryname] =>         [parent] => 1     )    [1] => array     (         [id] => 2         [categoryname] => b         [parent] =>2     )    [2] => array     (         [id] => 3         [categoryname] => c         [parent] => 2     ) ) , on... 

i wanted desired output should form of list

[    [      'id' => 1,      'categoryname' => 'a'   ],    [      'id' => 2,      'categoryname' => 'b'   ],    [      'id' => 3,     'categoryname' => 'b > c'   ],    [      'id' => 4,      'categoryname' => 'b>c>f'    ]  ]  

i had tried

when rows table , stores them in associative array. child-ids each branch node stored in associative array.

foreach ($rows $row){         $id = $row["id"];         $parent_id = $row["parent"] === null ? "null" : $row["parent"];         $data[$id] = $row;         $index[$parent_id][] = $id;     }     function display_child_nodes($parent_id, $level,$data,$index)     {          $parent_id = $parent_id === null ? "null" : $parent_id;         if (isset($index[$parent_id])) {             foreach ($index[$parent_id] $id) {                 $result['id'] = $data[$id]['id'];                 $result['name'] = $data[$id]['categoryname'];                 $result['level'] = $level;                 echo str_repeat("-", $level) . $data[$id]["categoryname"] . "\n";                 display_child_nodes($id, $level + 1,$data,$index);             }          }     }     display_child_nodes(null, 0,$data,$index); 

i followed reference result cant desired output.

i had gone through stack overflow question none useful me . can appreciated in advanced.

you can use iterators that. let's extend recursivearrayiterator , call new iterator adjacencylistiterator:

class adjacencylistiterator extends recursivearrayiterator {     private $adjacencylist;      public function __construct(         array $adjacencylist,         array $array = null,         $flags = 0     ) {         $this->adjacencylist = $adjacencylist;          $array = !is_null($array)             ? $array             : array_filter($adjacencylist, function ($node) {                 return is_null($node['parent']);             });          parent::__construct($array, $flags);     }      private $children;      public function haschildren()     {         $children = array_filter($this->adjacencylist, function ($node) {             return $node['parent'] === $this->current()['id'];         });          if (!empty($children)) {             $this->children = $children;             return true;         }          return false;     }      public function getchildren()     {         return new static($this->adjacencylist, $this->children);     } } 

by way, take notice, top level parents parent should null (and not same id).

having iterator can generate paths that:

$iterator = new recursiveiteratoriterator(     new adjacencylistiterator($rows),     recursiveiteratoriterator::self_first );  $path = []; foreach ($iterator $node) {     $depth = $iterator->getdepth();     $path[$depth] = $node['categoryname'];      echo implode(' > ', array_slice($path, 0, $depth + 1)), php_eol; } 

here working demo.

this approach can bit slower, custom recursive function. more flexible. changing mode of traversing, can leafs only, example:

$iterator = new recursiveiteratoriterator(     new adjacencylistiterator($rows) );  foreach ($iterator $leaf) {     echo $leaf['categoryname'], php_eol; } 

this case differs previous in set $mode of recursiveiteratoriterator default 1 recursiveiteratoriterator::leaves_only.


Comments

Popular posts from this blog

Is there a better way to structure post methods in Class Based Views -

performance - Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures? -

jquery - Responsive Navbar with Sub Navbar -