2015-05-03 3 views
0

В моем навигационном меню в настоящее время имеется две петли foreach; первая отобразит все родительские ссылки навигации, а вторая отобразит суб-навигационные ссылки.PHP - эффективность цикла foreach

Я искал способ изменить второй цикл foreach, чтобы перебирать только соответствующие элементы поднавигации, вместо того, чтобы проверять через каждую навигационную систему для каждого родительского элемента:.

Что было бы лучшим способом сделать это?

КОД:

<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

ОК, только первый подтвердите, пожалуйста, если я понял правильно - когда 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!

Смежные вопросы