Jump to content
php.lv forumi

Sub array menu


Go to solution Solved by codez,

Recommended Posts

Labvakar.

Cīnos ar funkciju, kas veido Nestable List no array.

 

Pašlaik ir izveidots arrays no kura mēģinu būvēt menu, bet loģiskajā shēmā tieku tikai līdz 2lvl menu items.

Cenšos rakt tālāk, bet zem 2lvl sub netieku.

Kur un kā likt nākamos blokus?

 

DB:

name       |id|url| position |  parent_id
---------------------------------------------------------------------
PHP         1  url    100            0  
CodeIgniter 4  url    100            1
HTML        10 url    100            0
CSS         11 url    100            10
Inline      12 url    100            11
Python      2  url    101            12

PHP:

public function create_menu()
{
    $this->db->order_by('position', 'asc'); 
    $query = $this->db->get('navigation');
    $output = '';
    $i = 0;

    foreach ($query->result_array() as $menuss){
    $i++;    
         $menu[$i]['id']           = $menuss['id'];      
         $menu[$i]['key']          = $menuss['parent_id'];      
         $menu[$i]['name']         = $menuss['name'];      
         $menu[$i]['url']          = $menuss['url'];      
         $menu[$i]['position']     = $menuss['position'];      
    }
    foreach  ($menu as $item)
    {
    $output .=   '<li data-id="'.$item['id'].'" class="dd-item">';    
        if ($item['key'] == 0) // root category
         {    
            $output .=      '<div class="dd-handle">'.$item['name'].'</div>';
         }
        else{
            ############SUB###############
            $output .= '<ol class="dd-list"><li data-id="'.$item['id'].'" class="dd-item">';
            $output .= '<div class="dd-handle">'.$item['name'].'</div>';
            $output .= '</li></ol>';
            ############SUB###############
        }    
    
        
        
    $output .=   '</li>';
    }   
    
   return $output;
    
    
}

Paldies par ieteikumiem ;)

Pieduriens.

Link to post
Share on other sites

Pārveido sarakstu koka struktūrā

$allItems = $query->result_array()
foreach ($allItems as $key => $value) {
    $allItems[$key]['children'] = array();
}

$addChildrens = function($item) use ($allItems, & $addChildrens) {
    foreach ($allItems as $i) {
        if ($i['parent_id'] == $item['id']) {
            $i['children'][] = $addChildrens($i);
        }
    }
    return $item;
};

$tree = array();
foreach ($allItems as $i) {
    if ($i['parent_id'] == 0) {
        $tree[] = $addChildrens($i);
    }
}
Edited by 101111
Link to post
Share on other sites
  • Solution

1. pārveido datus, tā, lai tie ir pieejami pēc id un lai katrs ieraksts satur visus child elementu id (metode set).

2. izmanto vienkāršu rekursīvu metodi, kurai padod kuri id ir jāizvada un tā attiecīgi izsauc pati sevi ar visiem apakš id un tā, kamēr vien id ir (metode show). $level tiek izmantots tīri noformējumam.

 

http://codepad.org/UzR7dTlJ

<?php

$data = array(
  array("id"=>1,"name"=>"CSS", pid=> 6),
  array("id"=>3,"name"=>"PHP", pid=> 0),
  array("id"=>6,"name"=>"HTML", pid=> 0),
  array("id"=>8,"name"=>"Controllers", pid=> 10),
  array("id"=>10,"name"=>"Kohana", pid=> 3),
  array("id"=>12,"name"=>"Models", pid=> 10)
);

Class Menu{
  public $items=array();
  public $root=array();
  public function set($data){
    foreach($data as $item){
      $this->items[$item['id']]=$item;
      $this->items[$item['id']]['childs']=array();
    }
    foreach($data as $item){
      if($item['pid']==0){
        array_push($this->root,$item['id']);   
      } else {    
        array_push($this->items[$item['pid']]['childs'],$item['id']);
      }
    }
  }
  function show($ids,$level=0){    
    foreach($ids as $id){
      echo str_repeat(".",$level*3).$this->items[$id]['name']."\n";
      $this->show($this->items[$id]['childs'],$level+1);
    }
  }
}

$menu = new Menu();
$menu->set($data);
$menu->show($menu->root);
Edited by codez
Link to post
Share on other sites

Ok, kā atsevišķa klase ārpus CI sistēmas viss Codez koks strādā.

Taču pievienojot Codez Menu klasi CI sistēmas library, ar echo rezultāti izvadās pirm html taga, ( ar return nestrādā

Cik saprotu ir jāizveido $outputs ar un tad jāatgriež, taču tādā gadijumā tieku tikai pie:

<ol class="dd-list"> PHPHTML </ol>

Library Menu Clase:

Class Menu{
  public $item=array();
  public $root=array();
  public function set($data){
    foreach($data as $item){
      $this->items[$item['id']]=$item;
      $this->items[$item['id']]['childs']=array();
    }
    foreach($data as $item){
      if($item['pid']==0){
        array_push($this->root,$item['id']);   
      } else {    
        array_push($this->items[$item['pid']]['childs'],$item['id']);
      }
    }
  }
  function show($ids,$level=0){ 
    $output = '';
    foreach($ids as $id){
      $output .= str_repeat('<ol class="dd-list"><li class="dd-item"><div class="dd-handle">',$level).$this->items[$id]['name'].str_repeat('</div></li></ol>',$level);
        
      $this->show($this->items[$id]['childs'],$level+1);
    }
    return $output;
  }
}

Controlieris:

    public function index(){
        $this->load->library('menu'); // <-- Codez Klase
           
        $a = $this->navigation_model->render_menu_array();     
        $b = $this->menu->set($a);
        $this->data['menu'] = $this->menu->show($this->menu->root);
        $this->render_page('admin/navigation');

    }


Ko daru nepareizi?

Paldies.

Edited by Pieduriens
Link to post
Share on other sites

Show funkcija izvada rezultātum nevis to atgriež.

Savukārt tev vajag, lai funkcija atgriež rezultātu, kuru tālāk padot templeitam, tātad tik tālu doma pareiza.

Tālāk vajag saprast kā strādā rekursija. Metode show atgriež menu html noteikta id elementiem.

Kad metode show pati sevī izsauc pati sevi, tā atgriež menu htmlu, kuŗš ir submenu konkrētajā brīdī apstrādātajam id.

Tātad arī tā atgrieztais html kods ir jāiekļauj:

http://codepad.org/jz2CGd2f

  function show($ids,$level=0){
    if (count($ids)==0) return "";
    $output = '';
    $output .= str_repeat(" ",$level*4).'<ul>'."\n";
    foreach($ids as $id){
      $output .= str_repeat(" ",$level*4+2).'<li>'."\n";
      $output .= str_repeat(" ",$level*4+4).$this->items[$id]['name']."\n";
      $output .= $this->show($this->items[$id]['childs'],$level+1);
      $output .= str_repeat(" ",$level*4+2).'<\li>'."\n";
    }
    $output .= str_repeat(" ",$level*4).'</ul>'."\n";
    return $output;
  }


P.S. Protams reālā kodā tos str_repeat un "\n" var mest ārā.

Edited by codez
Link to post
Share on other sites

Ok tiktāl taka būtu. Taču kādēļ klāt nācis $levelam: *4, un *4+2 ?

 

Reāli jūtos mazliet apjucis..

 

Vēlos šo izmantot, lai varu ubūvēt nestable list, bet izskatās ka tur style strutūra ir savādāka:


    <li data-id="1" class="dd-item"><button type="button" data-action="collapse">Collapse</button><button type="button" data-action="expand" style="display: none;">Expand</button>
            <div class="dd-handle">Item 1</div>
    <ol class="dd-list"><li data-id="11" class="dd-item">
            <div class="dd-handle">Item 11</div>
    </li></ol></li>
    <li data-id="2" class="dd-item"><button type="button" data-action="collapse">Collapse</button><button type="button" data-action="expand" style="display: none;">Expand</button>
            <div class="dd-handle">Item 2</div>
            <ol class="dd-list">
                    <li data-id="3" class="dd-item"><button type="button" data-action="collapse">Collapse</button><button type="button" data-action="expand" style="display: none;">Expand</button>
                            <div class="dd-handle">Item 3</div>
                    <ol class="dd-list"><li data-id="9" class="dd-item">
                            <div class="dd-handle">Item 9</div>
                    </li></ol></li>

            </ol>
    </li>

    <li data-id="5" class="dd-item"><button type="button" data-action="collapse">Collapse</button><button type="button" data-action="expand" style="display: none;">Expand</button>
        <div class="dd-handle">Item 5</div>
        <ol class="dd-list">
                <li data-id="6" class="dd-item"><button type="button" data-action="collapse">Collapse</button><button type="button" data-action="expand" style="display: none;">Expand</button>
                        <div class="dd-handle">Item 6</div>
                <ol class="dd-list"><li data-id="7" class="dd-item"><button type="button" data-action="collapse">Collapse</button><button type="button" data-action="expand" style="display: none;">Expand</button>
                        <div class="dd-handle">Item 7</div>
                <ol class="dd-list"><li data-id="8" class="dd-item"><button type="button" data-action="collapse">Collapse</button><button type="button" data-action="expand" style="display: none;">Expand</button>
                        <div class="dd-handle">Item 8</div>
                <ol class="dd-list"><li data-id="10" class="dd-item">
        <div class="dd-handle">Item 10</div>
</li></ol></li></ol></li></ol></li>


        </ol>
  </li>
Link to post
Share on other sites

str_repeat ir tikai tāpēc, lai html izvads būtu skārtots pa rindām, ja tas nav vajadzīgs, bez tā var iztikt un viss būs vienā rindā:

http://codepad.org/rSgPeS0O

  function show($ids,$level=0){
    if (count($ids)==0) return "";
    $output = '<ul>';
    foreach($ids as $id){
      $output .= '<li>';
      $output .= $this->items[$id]['name'];
      $output .= $this->show($this->items[$id]['childs'],$level+1);
      $output .= '<\li>';
    }
    $output .= '</ul>';
    return $output;
  }

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...