2015-05-03 174 views
0

我的導航菜單目前有兩個foreach循環;第一個將顯示所有父導航鏈接,第二個顯示子導航鏈接。PHP - foreach循環的效率

我正在尋找一種方法來更改第二個foreach循環,只循環通過相關的子導航項,而不是通過檢查每個父項的每個導航。

什麼是最好的方式去做這件事?

CODE:

<ul id="nav"> 
    <?php 
    if($grabNav = $db->prepare("SELECT caption,url,visibility,id,class,parent_id FROM navigation ORDER BY parent_id ASC, order_id ASC")) 
    { 
     $grabNav->execute(); 
     $grabNav = $grabNav->fetchAll(); 
     foreach($grabNav as $nav) 
     { 
      $visibility = true; 
      switch($nav['visibility']) 
      { 
       default: 
       case 0: $visibility = false; break; 
       case 1: $visibility = true; break; 
       case 2: if(LOGGED_IN && isset($cUser)) { $visibility = true; } else { $visibility = false; } break; 
       case 3: if(LOGGED_IN && isset($cUser)) { $visibility = false; } else { $visibility = true; } break; 
      } 
      if(!$visibility) { continue; } 
      if($nav['parent_id'] != -1) { continue; } 

      $class = $core->output($nav['class']); 
      if($nav['id'] == PAGE_ID) { $class .= ' selected'; } 
      echo '<li class="'.$class.'"><a href="'.$core->output($nav['url']).'">'.$core->output($nav['caption'],true).'</a><ul id="subNav">'; 
      foreach($grabNav as $sub) 
      { 
       if($sub['parent_id'] == $nav['id']) 
       { 
        $visibility = true; 
        switch($sub['visibility']) 
        { 
         default: 
         case 0: $visibility = false; break; 
         case 1: $visibility = true; break; 
         case 2: if(LOGGED_IN && isset($cUser)) { $visibility = true; } else { $visibility = false; } break; 
         case 3: if(LOGGED_IN && isset($cUser)) { $visibility = false; } else { $visibility = true; } break; 
        } 
        if(!$visibility) { continue; } 
        $subClass = $core->output($sub['class']); 
        echo'<li class="'.$subClass.'"><a href="'.$core->output($sub['url']).'">'.$core->output($sub['caption'],true).'</a></li>'; 
       } 
      } 
      echo'</ul></li>'; 
     } 
    } 
    ?> 
</ul> 

回答

1

@ Bing的答案是更好的解決方案,但如果你不喜歡用sql來做,你也可以創建新的樹型數組,其中根是父元素,但是在下一級 - 子級。您可以在可視化之前一次完成,之後再進行一次可視化。 如果不清楚 - 告訴我,我會告訴你前傳的示例代碼。

我希望下面的這些樣本將幫助:)

<?php 
// SAMPLE DATA 
$grabNav=array(
    0=>array('id'=>1,'parent_id'=>-1,'caption'=>'main-1'), 
    1=>array('id'=>3,'parent_id'=>1,'caption'=>'sub 1-1'), 
    2=>array('id'=>5,'parent_id'=>1,'caption'=>'sub 1-2'), 
    3=>array('id'=>7,'parent_id'=>2,'caption'=>'sub 2-1'), 
    4=>array('id'=>6,'parent_id'=>4,'caption'=>'sub 3-1'), 
    5=>array('id'=>2,'parent_id'=>-1,'caption'=>'home-2'), 
    6=>array('id'=>4,'parent_id'=>-1,'caption'=>'home-3'), 
    7=>array('id'=>8,'parent_id'=>-1,'caption'=>'home-4'), 
); 

$new_array=array(); 
// PRE - PASS to organize the results in the new tree-array 
foreach($grabNav as $nav){ 
    if($nav['parent_id']!=-1){ // children 
     if(!isset($new_array[$nav['parent_id']])){ 
      $new_array[$nav['parent_id']]=array(
       'data'=>array(), 
       'sub'=>array(), 
      ); 
     } 
     $new_array[$nav['parent_id']]['sub'][$nav['id']]=$nav; 
    } 
    else { // parent 
     if(!isset($new_array[$nav['id']])){ 
      $new_array[$nav['id']]=array(
       'data'=>array(), 
       'sub'=>array(), 
      ); 
     } 
     $new_array[$nav['id']]['data']=$nav; 
    } 
} 
// VISUALIZATION 
foreach($new_array as $root){ 
    echo $root['data']['caption']."<br/>"; 
    foreach($root['sub'] as $branch){ 
     echo "--- ".$branch['caption']."<br/>"; 
    } 
} 
?> 
<pre><?= print_r($new_array) ?></pre> 
+0

呀一些例子可能將是巨大的,:) – zuc0001

+0

OK,只有首先確認請,如果我理解正確的 - 當PARENT_ID = -1,那麼它是第一級 - 對吧? –

+0

這是正確的:) 大於-1的任何項都是相應父項的子項。 – zuc0001

2

在你的初始查詢db->prepare("SELECT caption,url,visibility,id,class,parent_id FROM navigation ORDER BY parent_id ASC, order_id ASC"))你可以JOIN與同桌ON navigation.parent_id=id

您需要枚舉所選字段以避免「發現多個」SQL錯誤,例如SELECT orig.caption AS caption FROM navigation JOIN navigation ON parent_id=id。注意orig.caption AS caption位!