【问题标题】:PHP - efficiency of foreach loopPHP - foreach 循环的效率
【发布时间】:2015-07-12 18:52:43
【问题描述】:

我的导航菜单目前有两个 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>

【问题讨论】:

    标签: php mysql pdo mysqli foreach


    【解决方案1】:

    在您的初始查询 db-&gt;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 位!

    【讨论】:

      【解决方案2】:

      @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>
      

      【讨论】:

      • 是的,一些例子可能会很棒,:)
      • 好的,如果我理解正确,请先确认-当parent_id = -1时,首先是-根级别-对吗?
      • 这是正确的 :) 任何大于 -1 的都是相应父项的子项。
      • 干得好!这对我来说很有意义,我现在对导航列表有了一个好主意。感激不尽!
      猜你喜欢
      • 2016-09-02
      • 2015-10-13
      • 2015-07-20
      • 2012-03-02
      • 1970-01-01
      • 1970-01-01
      • 2016-09-26
      • 2012-07-19
      • 2015-12-10
      相关资源
      最近更新 更多