2017-04-15 21 views
0

このクラスは、WordPressメニュー構造(入れ子配列/オブジェクト)を反復して完成したメニューを生成するように設計されています。私のデータのソースはWordPressですが、この問題はWP.SOの代わりにSOに属していると思います。なぜならPHPで問題がより根付いているからです(再帰を試みる人には当てはまります)。ループ時に繰り返し結果を生成するforeach()

何らかの理由で、階層内に重複した結果が表示されています。また、特定のHTML要素が適切に閉じられていないことに気づいています。私はすべてを適切に入れ子にしたようですが、結果はここにあります。

デバッグを支援するために、私は視覚的にマークアップに影響を与えるために*を追加しました。たぶんあなたは私がしていないことを知っているかもしれません。指が交差して、あなたの入力に事前に感謝!バックエンドでの


私のクラス

class Nav_Menu 
{ 
    public $wp_nav; 
    public $nested_nav; 
    public $recursion_depth = 0; 

    function __construct($menu, $args = array()) 
    { 
     $format = new Format; 

     if($menu) 
     { 
      $this->wp_nav = wp_get_nav_menu_items($menu, $args); 
      $this->nested_nav = $this->build_tree($this->wp_nav); 

      $output = $this->build_output($this->nested_nav); 
      $output_formatted = $format->HTML($output); 

      // echo $output; 
      echo $output_formatted; 
     } 
    } 

    private function build_output($menu = array()) 
    { 
     $output = '**'; 
     $output.= $this->recurse_menu($menu, $output); 

     return $output; 
    } 

    private function recurse_menu($menu = array(), $output) 
    { 
     global $post; 

     if(!empty($menu) && !empty($output)) 
     { 
      $this->recursion_depth++; 

      // ul classes 
      $classes_ul = array(); 
      $classes_ul[] = ($this->recursion_depth > 1 ? 'sub-menu' : ''); 
      $classes_ul[] = 'depth-' . $this->recursion_depth; 

      // process list wrappers 
      $output.= '<ul class="' . $this->process_classes($classes_ul) . '">'; 

      // loop through menu items 
      foreach($menu as $menu_key => $menu_val) 
      { 
       // process list items 
       $output.= '<li>' . $menu_val->title; 

       // if necessary, handle children and recurse 
       if(!empty($menu_val->children)) 
       { 
        // recurse, and call this again 
        $output.= $this->recurse_menu($menu_val->children, $output); 
       } 

       // process list items 
       $output.= '</li>'; 
      } 

      // process list wrappers 
      $output.= '</ul>'; 
     } 

     return $output; 
    } 

    private function process_classes($classes = array()) 
    { 
     if(!$classes) 
     { 
      return; 
     } 

     return trim(implode(' ', $classes)); 
    } 

    private function build_tree($elements = array(), $parent_id = 0) 
    { 
     $branch = array(); 
     foreach($elements as $element) 
     { 
      if ($element->menu_item_parent == $parent_id) 
      { 
       $children = $this->build_tree($elements, $element->ID); 
       if ($children) 
       { 
        $element->children = $children; 
       } 

       $branch[] = $element; 
      } 
     } 

     return $branch; 
    } 
} 

$mynav = new Nav_Menu('Test Menu'); 

結果の出力

**** 
<ul class="depth-1"> 
    <li> 
     One** 
     <ul class="depth-1"> 
      <li> 
       One 
       <ul class="sub-menu depth-2"> 
        <li> 
         Sub One 
        </li> 
        <li> 
         Sub Two 
        </li> 
        <li> 
         Sub Three 
        </li> 
       </ul> 
      </li> 
      <li> 
       Two 
      </li> 
      <li> 
       Three** 
       <ul class="depth-1"> 
        <li> 
         One** 
         <ul class="depth-1"> 
          <li> 
           One 
           <ul class="sub-menu depth-2"> 
            <li> 
             Sub One 
            </li> 
            <li> 
             Sub Two 
            </li> 
            <li> 
             Sub Three 
            </li> 
           </ul> 
          </li> 
          <li> 
           Two 
          </li> 
          <li> 
           Three 
           <ul class="sub-menu depth-3"> 
            <li> 
             Sub One 
            </li> 
            <li> 
             Sub Two 
            </li> 
           </ul> 
          </li> 
          <li> 
           Four 
          </li> 
         </ul> 

WordPressのメニュー

WordPress navigation menu

+0

また、 '$ output_formatted'の代わりに' $ output'をエコーすると、同じ結果が生成されます。ちょうど連結されています。私はあなたがこのポストで "Format"クラスを見逃していることに気づき、ここに掲載されたコードに問題があることを皆に保証したいと思っていました。 –

答えて

0

誰かがその理由を知っていたら、私は知りたいと思うので、私は今のところ答えを選びます。私の推測は変数$outputの奇妙な名前空間/スコープの問題です。誰が知っている、私は今ちょっと疲れている。合法的な構造を得るために

修正は出力

<ul class="depth-1"> 
    <li> 
     One 
     <ul class="sub-menu depth-2"> 
      <li> 
       Sub One 
      </li> 
      <li> 
       Sub Two 
      </li> 
      <li> 
       Sub Three 
      </li> 
     </ul> 
    </li> 
    <li> 
     Two 
    </li> 
    <li> 
     Three 
     <ul class="sub-menu depth-3"> 
      <li> 
       Sub One 
      </li> 
      <li> 
       Sub Two 
      </li> 
     </ul> 
    </li> 
    <li> 
     Four 
    </li> 
</ul> 

を結果として生じる。この...


クラス

class Nav_Menu 
{ 
    public $wp_nav; 
    public $nested_nav; 
    public $recursion_depth = 0; 
    public $output = ''; 

    function __construct($menu, $args = array()) 
    { 
     $format = new Format; 

     if($menu) 
     { 
      $this->wp_nav = wp_get_nav_menu_items($menu, $args); 
      $this->nested_nav = $this->build_tree($this->wp_nav); 

      $this->build_output($this->nested_nav); 
      $output_formatted = $format->HTML($this->output); 

      // echo $this->output; 
      echo $output_formatted; 
     } 
    } 

    private function build_output($menu = array()) 
    { 
     $this->recurse_menu($menu); 
    } 

    private function recurse_menu($menu = array()) 
    { 
     global $post; 

     if(!empty($menu)) 
     { 
      $this->recursion_depth++; 

      // ul classes 
      $classes_ul = array(); 
      $classes_ul[] = ($this->recursion_depth > 1 ? 'sub-menu' : ''); 
      $classes_ul[] = 'depth-' . $this->recursion_depth; 

      // process list wrappers 
      $this->output.= '<ul class="' . $this->process_classes($classes_ul) . '">'; 

      // loop through menu items 
      foreach($menu as $menu_key => $menu_val) 
      { 
       // process list items 
       $this->output.= '<li>'; 
       $this->output.= $menu_val->title; 

       // if necessary, handle children and recurse 
       if(!empty($menu_val->children)) 
       { 
        // recurse, and call this again 
        $this->recurse_menu($menu_val->children); 
       } 

       // process list items 
       $this->output.= '</li>'; 
      } 

      // process list wrappers 
      $this->output.= '</ul>'; 
     } 
    } 

    private function process_classes($classes = array()) 
    { 
     if(!$classes) 
     { 
      return; 
     } 

     return trim(implode(' ', $classes)); 
    } 

    private function build_tree($elements = array(), $parent_id = 0) 
    { 
     $branch = array(); 
     foreach($elements as $element) 
     { 
      if ($element->menu_item_parent == $parent_id) 
      { 
       $children = $this->build_tree($elements, $element->ID); 
       if ($children) 
       { 
        $element->children = $children; 
       } 

       $branch[] = $element; 
      } 
     } 

     return $branch; 
    } 
} 

$mynav = new Nav_Menu('Test Menu'); exit; 

だった私はちょうどのためのプライベート変数を作成しましたクラスと、私はそれを記憶域として参照する必要があるたびにイオン、私はちょうどそれに追加します。これまでと同じですが、それ以上の奇妙なメソッドチェーンを$outputに渡す必要はありません。

コミュニティに役立つ他のアイデアがあれば誰でも共有してください!

0

以下のようにあなたのbuild_output方法更新:

private function build_output($menu = array()) 
{ 
    $output = '<ul>'; 
    $output = $this->recurse_menu($menu, $output); 
    $output.= '</ul>'; 
    return $output; 
} 

は、以下のようにあなたのrecurse_menu方法を更新します。

private function recurse_menu($menu = array(), $output = '') 
{ 
    global $post; 
    if(!empty($menu)) 
     { 
     $this->recursion_depth++; 
     // ul classes 
     $classes_ul = array(); 
     $classes_ul[] = ($this->recursion_depth > 1 ? 'sub-menu' : ''); 
     $classes_ul[] = 'depth-' . $this->recursion_depth; 

     // loop through menu items 
     foreach($menu as $menu_key => $menu_val) 
     { 
      // if necessary, handle children and recurse 
      if(!empty($menu_val->children)) 
      { 
       // recurse, and call this again 
       $output.= '<li><a href="#">'.$menu_val->title.'</a><ul class="' . $this->process_classes($classes_ul) . '">'.$this->recurse_menu($menu_val->children).'</ul></li>'; 

      } 
      else { 
      $output.= '<li><a href="#">'.$menu_val->title.'</a></li>'; 
      } 

     } 
    } 

    return $output; 
} 

注:私は、より一層のサブレベルでそれをテストし、それきましたうまくいきます。

関連する問題