2012-03-23 34 views
1

我已經MPTT對象$pages 通過MPTT樹菜單

foreach ($pages as $p): 
    echo str_repeat('&nbsp;', 2 * $p->lvl).$p->nav.'<br/>'; 
endforeach; 

它的結構看起來像http://pastebin.com/CSGenz7y

我需要呈現導航菜單。使用下面的代碼:

echo '<ul id="jMenu">'; 
    $idn = 1; 
    foreach ($pages as $s): 
     if($s->lvl > $idn) 
     { 
     for($i=$s->lvl-$idn; $i>=1; $i--) echo '<ul>'; 
     } 
     elseif($s->lvl < $idn) 
     { 
     for($i=$idn-$s->lvl; $i>=1; $i--) echo '</ul>'; 
     } 
     $idn = $s->lvl; 
     echo '<li>'.$s->nav.'</li>'; 
    endforeach; 
    for($i=$s->lvl; $i>=1; $i--) echo '</ul>'; 
    echo '</ul>'; 

我獲得以下的輸出:http://pastebin.com/MDMM2FcD

但我需要所有的孩子UL李是家長裏內:http://pastebin.com/JteBPGqb

我花了半天時間,與無疾而終, 有任何想法嗎?

回答

1

你應該等待陣列的下一個孩子關閉li。試試這個代碼:

echo '<ul id="jMenu">'; 
$idn = 1; 
foreach ($pages as $s): 

    echo '<li>'.$s->nav; 

    if($s->lvl > $idn){ 
     for($i=$s->lvl-$idn; $i>=1; $i--) echo '<ul>'; 
    } 
    elseif($s->lvl < $idn) { 
     for($i=$idn-$s->lvl; $i>=1; $i--) echo '</li></ul></li>'; 
    } 
    else { 
     echo '</li>'; 
    } 

    $idn = $s->lvl; 


endforeach; 
for($i=$s->lvl; $i>=1; $i--) echo '</ul></li>'; 
echo '</ul>'; 
+0

再次更新,請 – safarov 2012-03-29 19:38:36

+0

更新:http://pastebin.com/22pwY8Wt – nazarov 2012-03-29 19:42:42

+0

這裏是原始數組: HTTP:// pastebin.com/FyRWJETr – nazarov 2012-03-29 21:14:05

0

這個實現應該允許更容易的自定義。

用法:

<?php $orderLevelList = new OrderedLevelList; ?> 
<ul class="main-menu"> 
<?php echo $orderLevelList->render($pages) ?> 
</ul> 

代碼:

<?php 
/** 
* Menu generator - expects that outer UL already exists (to allow custom class for example) 
*/ 
class OrderedLevelList 
{ 
    /** 
    * Renders list 
    * 
    * @param array $pages array 
    * @return string 
    */ 
    public function render($pages) 
    { 
     $result = ''; 
     $lastLevel = $this->_getIntialLevel(); 
     foreach ($pages as $page) { 
      $pageLevel = $this->_getLevel($page); 
      if ($pageLevel > $lastLevel) { 
       $result .= $this->_openList($pageLevel); 
      } elseif ($pageLevel < $lastLevel) { 
       $levelDiff = $lastLevel - $pageLevel; 
       for ($i = $levelDiff; $i >= 0; $i--) { 
        $result .= $this->_closeList($pageLevel); 
        $result .= $this->_closeItem(); 
       } 
      } else { 
       $result .= $this->_closeItem(); 
      } 
      $result .= $this->_openItem($page); 
      $result .= $this->_renderItem($page); 
      $lastLevel = $pageLevel; 
     } 
     $result .= $this->_closeItem(); 
     return $result; 
    } 

    /** 
    * Renders contents of the item (what's inside the item) 
    * 
    * @param mixed $page 
    * @return string 
    */ 
    protected function _renderItem($page) 
    { 
     return sprintf('<a href="%s">%s</a>', $page['url'], $page['name']); 
    } 

    /** 
    * Accessor for the level attribute 
    * 
    * Can be overridden if you use objects instead of associative arrays 
    * 
    * @param mixed $page 
    * @return int 
    */ 
    protected function _getLevel($page) 
    { 
     return $page['level']; 
    } 

    /** 
    * Opens new level of list 
    * 
    * Can be overridden if you want for example OLs 
    * 
    * @param int $currentLevel 
    * @return string 
    */ 
    protected function _openList($currentLevel) 
    { 
     return sprintf('<ul class="%s">', 'level-' . $currentLevel); 
    } 

    /** 
    * Opens new item of list 
    * 
    * Override if you need more complex markup of items 
    * 
    * @param mixed $page 
    * @return string 
    */ 
    protected function _openItem($page) 
    { 
     return sprintf('<li class="%s">', 'item-' . $page['id']); 
    } 

    /** 
    * Closes current level of the list 
    * 
    * @param int $currentLevel 
    * @return string 
    */ 
    protected function _closeList($currentLevel) 
    { 
     return '</ul>'; 
    } 

    /** 
    * Closes the previous item 
    * 
    * The actual item being closed cannot be accessed due to 
    * the way the algorithm works 
    * 
    * @return string 
    */ 
    protected function _closeItem() 
    { 
     return '</li>'; 
    } 

    /** 
    * @return int 
    */ 
    protected function _getIntialLevel() 
    { 
     return 1; 
    } 
}