php - recursion - How to construct a data tree without ids, data is ambigious. -
please refer solution, has been solved.
i have following dataset , no ids provided, trying completed using recursion.
should attempt or should go route? because there no ids.
after filter on each attribute root gender, node 1 category , end node label. have tried use array_merge_recursive, array_push , have tried construct own recursive pattern nothing appears pattern want.
json data:
[{"label":"shirts","tag":"m_shirt","gender":"men","category":"clothing"}, {"label":"pants","tag":"m_pant","gender":"men","category":"clothing"}, {"label":"shorts","tag":"m_short","gender":"men","category":"clothing"}, {"label":"casual","tag":"m_shoe_casual","gender":"men","category":"shoes"}, {"label":"tennis","tag":"m_shoe_tennis","gender":"men","category":"shoes"}, {"label":"watches","tag":"m_access_watch","gender":"men","category":"accessories"}, {"label":"belts","tag":"m_access_belt","gender":"men","category":"accessories"}, {"label":"ties","tag":"m_access_tie","gender":"men","category":"accessories"}] men ->accessories ->watches ->belts ->ties ->clothing ->pants ->shirts ->shorts ->shoes ->casual ->tennis
here php code recursion messy:
function buildsidebar($searchlayers){ try{ $sidebar; $count = 0; foreach($searchlayers[$count] $root){ //$sidebardata[]=array("root"=>$root); $sidebardata[]=$root; $searchlayers[$count]=''; $this->addchildren($sidebardata,$searchlayers,1,$root, $count); $count++; } var_dump($sidebardata); }catch (exception $ex){ log($ex); } } function addchildren(&$sidebardata,$layers,$level,$parent,$count){ if(!empty($layers[$level]) && is_array($layers[$level])){ foreach($layers[$level] $child){ //check if child node if($this->verifychildbelongstoparent($child,$parent)){ if($level==1) { $count = 0; // $sidebardata = array_merge_recursive($sidebardata, array("root"=>array("child".$level=>$child))); $sidebardata[0][$level] = $child; } else { $sidebardata[][][$level] = $child; } $parents[]=$parent; $parents[]=$child; //var_dump($parents); if($level<3) { // $this->addchildren($sidebardata,$layers,$level++,$parents); } } // } } } function verifychildbelongstoparent($child,$parent){ //var_dump($this->categorydata);break; foreach($this->categorydata $category){ if(is_array($parent) && sizeof($parent)>1){ echo 'child' . $child; echo 'parents '; var_dump($parent); var_dump($category); if(strcmp($category->getgender(),$parent[0])==0 && strcmp($category->getcategory(),$parent[1])==0) { var_dump($child); echo 'add child ' . $child; return true; } } else{ //echo 'check if ' . $parent .' has child ' . $child; if(strcmp($category->getgender(),$parent)==0) { // var_dump($parent); // var_dump($child); // echo 'add child'; return true; } } } return false; }
here $searchlayers data pass in:
array ( [0] => "men", [1] => array( [0]=>'accessories', [1]=>'clothing', [2]=>'shoes' ), [2] =>array( [0]=>'belts', [1]=>'casual', [2]=>'shirts', [3]=>'shorts', [4]=>'tennis', [5]=>'ties', [6]=>'watches' ) );
so here's solution, there maybe better one, attempted 3 different techniques thinking scalable.
i placed following limitations on design, side menu bar can 3 levels deep.
with sorted data find out grandparent, parent, child detailed in $searchlayers
above, passed 3 separate arrays ($layer1, $layer2, $layer3
) comply parental hierarchy.
here code, starts calling top function function buildsidemenu($layer1,$layer2,$layer3)
//starts construction of side menu , adds each layer of children parent function buildsidemenu($layer1, $layer2, $layer3){ $sidemenu = '<ul class="nav nav-stacked">'; foreach($layer1 $layer){ $sidemenu.= '<li><a class="expandable" href="#">'.$layer.'</a></li>'; //adds children founded parent $sidemenu .= $this->buildsidemenuchildern($layer,$layer2,$layer3); } $sidemenu .= '</ul>'; $this->sidemenu = $sidemenu; } //builds on children side bar belogn parent function buildsidemenuchildern($parent,$layer1,$layer2=''){ $entries =''; foreach($layer1 $layer){ //deter mines if child belongs parent if($this->islayerparentmatch($layer,$parent)){ //if child has it's own childern, process needs repeated, else child leaf (aka end node) if(!empty($layer2)){ $entries .= '<li><a class="expandable" href="/'.$this->gettag($layer).'">'.$layer.'</a></li>'; $entries .= $this->buildsidemenuchildern(array($parent,$layer),$layer2); }else{ $entries .= '<li><a href="/'.$this->gettag($layer).'">'.$layer.'</a></li>'; } } } $entries = (!empty($entries))? '<ul style="display:block;">'.$entries.'</ul>':$entries; return $entries; } //populates href tag if 1 available, converts text lower case function gettag($label){ foreach($this->categorydata $category){ if(strcmp($label,$category->getlabel())==0) { return $category->gettag(); } } return '#'. strtolower($label); } //determines if child associated parents provided function islayerparentmatch($child,$parent){ if(empty($child) || empty($parent)) return false; foreach($this->categorydata $category){ if(!is_array($parent) && strcmp($category->getgender(),$parent)==0 && strcmp($category->getcategory(),$child)==0) { return true; }else if(strcmp($category->getgender(),$parent[0])==0 && strcmp($category->getcategory(),$parent[1])==0 && strcmp($category->getlabel(),$child)==0){ return true; } } return false; } function getsidemenu(){ return $this->sidemenu; }
please note, converted json data php class of category in had getters , setters each of attributes defined in json data. class has been omitted code.
Comments
Post a Comment