Le navigateur de navigation personnalisé affiche les enfants de l'élément de menu actuel ou les frères et sœurs sur aucun enfant

14

Cela fait des heures que je déconne / cherche et je n'arrive toujours pas à faire fonctionner cela, alors je cède enfin et demande de l'aide.

J'essaie d'écrire un marcheur personnalisé qui affiche uniquement les enfants des pages actuelles, ou s'il n'y a pas d'enfants, affiche les frères et sœurs des pages.

Par exemple, prenez l'arborescence de menus suivante:

  • 1.0
    • 1.2.0
      • 1.3.0
      • 1.3.1
      • 1.3.2
    • 1.2.1
    • 1.2.2
  • 2.0

Supposons que je suis sur la page actuelle 1.2.0. Sur cette page, je veux afficher ses enfants (1.3.0, 1.3.1, 1.3.2)

cependant, si je suis sur la page 1.2.2, car il n'a pas d'enfants, il devrait afficher ses frères et sœurs de niveau actuel, donc il devrait me montrer (1.2.0, 1.2.1, 1.2.2).

jchamb
la source
4
Veuillez déplacer votre solution vers une réponse afin qu'elle soit plus claire pour les autres et que les questions ne hantent pas le site comme étant sans réponse.
1er
Ce que @Rarst a dit! J'ai presque manqué que vous trouviez une solution.
Chris Krycho
Réponse de Necro. J'ai posé plus ou moins la même question sur SO il y a environ 2 ans avec une très bonne réponse. stackoverflow.com/questions/5826609/…
Stoosh
Réponse déplacée à l'intérieur de la question pour une réponse séparée. OP: Veuillez suivre là-bas.
kaiser

Réponses:

4

Il s'agit du déambulateur que j'ai utilisé pour afficher uniquement les enfants de l'élément de menu actuel. Ou les éléments de menu frères et sœurs s'il n'a pas d'enfants.

Il y a des commentaires tout au long de la classe expliquant chaque section

<?php

class SH_Child_Only_Walker extends Walker_Nav_Menu {

private $ID;
private $depth;
private $classes = array();
private $child_count = 0;
private $have_current = false;


// Don't start the top level
function start_lvl(&$output, $depth=0, $args=array()) {

    if( 0 == $depth || $this->depth != $depth )
        return;

    parent::start_lvl($output, $depth,$args);
}

// Don't end the top level
function end_lvl(&$output, $depth=0, $args=array()) {
    if( 0 == $depth || $this->depth != $depth )
        return;

    parent::end_lvl($output, $depth,$args);
}

// Don't print top-level elements
function start_el(&$output, $item, $depth=0, $args=array()) {

    $is_current = in_array('current-menu-item', $this->classes);

    if( 0 == $depth || ! $is_current )
        return;

    parent::start_el($output, $item, $depth, $args);
}

function end_el(&$output, $item, $depth=0, $args=array()) {
    if( 0 == $depth )
        return;

    parent::end_el($output, $item, $depth, $args);
}

// Only follow down one branch
function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {

    // Check if element is in the current tree to display
    $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );
    $this->classes = array_intersect( $current_element_markers, $element->classes );

    // If element has a 'current' class, it is an ancestor of the current element
    $ancestor_of_current = !empty($this->classes);

    // check if the element is the actual page element we are on.
    $is_current = in_array('current-menu-item', $this->classes);

    // if it is the current element
    if($is_current) {

        // set the count / ID / and depth to use in the other functions.
        $this->child_count = ( isset($children_elements[$element->ID]) ) ? count($children_elements[$element->ID]) : 0;
        $this->ID = $element->ID;
        $this->depth = $depth;
        $this->have_current = true;

        if($this->child_count > 0) {

            // if there are children loop through them and display the kids.
            foreach( $children_elements[$element->ID] as $child ) {
                parent::display_element( $child, $children_elements, $max_depth, $depth, $args, $output );
            }

        } else {
            // no children so loop through kids of parent item.
            foreach( $children_elements[$element->menu_item_parent] as $child ) {
                parent::display_element( $child, $children_elements, $max_depth, $depth, $args, $output );
            }

        }
    }

    // if depth is zero and not in current tree go to the next element
    if ( 0 == $depth && !$ancestor_of_current)
        return;

    // if we aren't on the current element proceed as normal
    if(! $this->have_current )
        parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
}
}

Attachez-le comme vous le feriez avec n'importe quel autre déambulateur personnalisé sur un wp_nav_menu

<?php
wp_nav_menu( array(
    'menu' => 'primary-menu'
    ,'container' => 'nav'
    ,'container_class' => 'subpages'
    ,'depth' => 0
    ,'walker' => new SH_Child_Only_Walker()
 ));
?>
jchamb
la source
Je veux souligner le commentaire de @ Stoosh pointant ici. stackoverflow.com/questions/5826609/… car c'est une autre bonne solution
jchamb
0

J'ai eu une expérience similaire. Vous voudrez peut-être penser à sortir la logique des pages du déambulateur. Fondamentalement, compilez la hiérarchie de pages actuelle en tant qu'objet. Utilisez ensuite le paramètre 'exclude' dans la fonction wp_nav_menu. Maintenant, les pages exclues dépendraient si la page actuelle a des enfants. Si aucun enfant ne montre de frères; si les enfants && ces enfants sont la fin de la ligne, montrez frères et enfants; si des enfants et des petits-enfants existent, excluez les frères et montrez les enfants et les petits-enfants.

Steve Fischer
la source
Quel est ce excludeparamètre auquel vous vous référez? Je regarde la documentation et je n'y vois aucune référence.
Chris Krycho
1
Je m'excuse de m'être trompé. Vous avez raison, il n'y a pas de paramètre «exclure». Je voulais utiliser la fonction "wp_list_pages".
Steve Fischer
Très bien, et pas de soucis. J'étais simplement curieux de savoir s'il y avait quelque chose sans papiers mais à l'arrière-plan — j'ai déjà vu cela se produire. Merci de l'avoir éclairci! Je n'avais pas pensé à utiliser wp_list_pages()dans ce contexte, c'est donc une idée intéressante.
Chris Krycho