我相信wp_nav_menu()
处理顶级列表换行,以便start_lvl
方法将只处理子菜单项(据我所知)。它也不能让我们访问$item
我们需要找到父母。
下面我设置了一个布尔变量来跟踪我们是否应该显示标题。它还可以保持HTML的有效性,列表只能包含列表项,因此最好使用特定的类来设置列表项的样式。以下代码90%取自Core WP_Nav_Menu Walker
首先,我们需要设置变量:
class Title_Sub_Menus extends Walker_Nav_Menu {
/**
* Track Whether to show parent title
*
* @var Boolean
*/
private $show_parent_title = false;
/* ... */
}
接下来,每当创建新的子菜单时,我们需要打开开关变量:
class Title_Sub_Menus extends Walker_Nav_Menu {
/* ... */
/**
* Starts the list before the elements are added.
*
* @since 3.0.0
*
* @see Walker::start_lvl()
*
* @param string $output Used to append additional content (passed by reference).
* @param int $depth Depth of menu item. Used for padding.
* @param stdClass $args An object of wp_nav_menu() arguments.
*/
public function start_lvl( &$output, $depth = 0, $args = array() ) {
if ( isset( $args->item_spacing ) && \'discard\' === $args->item_spacing ) {
$t = \'\';
$n = \'\';
} else {
$t = "\\t";
$n = "\\n";
}
$indent = str_repeat( $t, $depth );
// Default class.
$classes = array( \'sub-menu\' );
// Enable Submenu Title
$this->show_parent_title = true;
/**
* Filters the CSS class(es) applied to a menu list element.
*
* @since 4.8.0
*
* @param array $classes The CSS classes that are applied to the menu `<ul>` element.
* @param stdClass $args An object of `wp_nav_menu()` arguments.
* @param int $depth Depth of menu item. Used for padding.
*/
$class_names = join( \' \', apply_filters( \'nav_menu_submenu_css_class\', $classes, $args, $depth ) );
$class_names = $class_names ? \' class="\' . esc_attr( $class_names ) . \'"\' : \'\';
$output .= "{$n}{$indent}<ul$class_names>{$n}";
}
/* ... */
} // END class Title_Sub_Menus
这就是事情变得有点棘手的地方。据我所知,如果菜单项对象标题没有从原始标题更改,则不会与该项一起保存。如果原始页面标题为“WordPress页面”,并且在将菜单项添加到菜单后将其标题更改为“WordPress”,则会将其保存到菜单项中。我们还应该对照条款进行检查。
Kudos to Alex Sancho\'s answer.Class Title_Sub_Menus extends Walker_Nav_Menu {
/* ... */
/**
* Starts the element output.
*
* @since 3.0.0
* @since 4.4.0 The {@see \'nav_menu_item_args\'} filter was added.
*
* @see Walker::start_el()
*
* @param string $output Used to append additional content (passed by reference).
* @param WP_Post $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $id Current item ID.
*/
public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
// Maybe show parent title
if( 0 === $depth && $this->show_parent_title ) {
// Grab the title if the user HAS changed it from the original
$title = get_the_title( $item->menu_item_parent );
if( empty( $title ) ) {
// Title is the original title, grab it from the original post or term.
$object_id = get_post_meta( $item->menu_item_parent, \'_menu_item_object_id\', true );
$object = get_post_meta( $item->menu_item_parent, \'_menu_item_object\', true );
$type = get_post_meta( $item->menu_item_parent, \'_menu_item_type\', true );
if ( \'post_type\' === $type ) {
$title = get_post( $object_id )->post_title;
} elseif ( \'taxonomy\' === $type) {
$title = get_term( $object_id, $object )->name;
}
}
$output .= sprintf( \'<li class="parentTitle"><h3>%1$s</h3></li>\', $title ); // Display our title
// Parent title displayed, turn off switch
$this->show_parent_title = false;
}
/* ... */
}
} // END class Title_Sub_Menus
全班
class Title_Sub_Menus extends Walker_Nav_Menu {
/**
* Track Whether to show parent title
*
* @var Boolean
*/
private $show_parent_title = false;
/**
* Starts the list before the elements are added.
*
* @since 3.0.0
*
* @see Walker::start_lvl()
*
* @param string $output Used to append additional content (passed by reference).
* @param int $depth Depth of menu item. Used for padding.
* @param stdClass $args An object of wp_nav_menu() arguments.
*/
public function start_lvl( &$output, $depth = 0, $args = array() ) {
if ( isset( $args->item_spacing ) && \'discard\' === $args->item_spacing ) {
$t = \'\';
$n = \'\';
} else {
$t = "\\t";
$n = "\\n";
}
$indent = str_repeat( $t, $depth );
// Default class.
$classes = array( \'sub-menu\' );
$this->show_parent_title = true;
/**
* Filters the CSS class(es) applied to a menu list element.
*
* @since 4.8.0
*
* @param array $classes The CSS classes that are applied to the menu `<ul>` element.
* @param stdClass $args An object of `wp_nav_menu()` arguments.
* @param int $depth Depth of menu item. Used for padding.
*/
$class_names = join( \' \', apply_filters( \'nav_menu_submenu_css_class\', $classes, $args, $depth ) );
$class_names = $class_names ? \' class="\' . esc_attr( $class_names ) . \'"\' : \'\';
$output .= "{$n}{$indent}<ul$class_names>{$n}";
}
/**
* Starts the element output.
*
* @since 3.0.0
* @since 4.4.0 The {@see \'nav_menu_item_args\'} filter was added.
*
* @see Walker::start_el()
*
* @param string $output Used to append additional content (passed by reference).
* @param WP_Post $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $id Current item ID.
*/
public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
// Maybe show parent title
if( 0 === $depth && $this->show_parent_title ) {
$object_id = get_post_meta( $item->menu_item_parent, \'_menu_item_object_id\', true );
$object = get_post_meta( $item->menu_item_parent, \'_menu_item_object\', true );
$type = get_post_meta( $item->menu_item_parent, \'_menu_item_type\', true );
$title = get_the_title( $item->menu_item_parent );
if( empty( $title ) ) {
if ( \'post_type\' == $type ) {
$title = get_post( $object_id )->post_title;
} elseif ( \'taxonomy\' == $type) {
$title = get_term( $object_id, $object )->name;
}
}
$output .= sprintf( \'<li class="parentTitle"><h3>%1$s</h3></li>\', $title ); // OR post_parent if dynamically generated
$this->show_parent_title = false;
}
if ( isset( $args->item_spacing ) && \'discard\' === $args->item_spacing ) {
$t = \'\';
$n = \'\';
} else {
$t = "\\t";
$n = "\\n";
}
$indent = ( $depth ) ? str_repeat( $t, $depth ) : \'\';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = \'menu-item-\' . $item->ID;
/**
* Filters the arguments for a single nav menu item.
*
* @since 4.4.0
*
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param WP_Post $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
*/
$args = apply_filters( \'nav_menu_item_args\', $args, $item, $depth );
/**
* Filters the CSS class(es) applied to a menu item\'s list item element.
*
* @since 3.0.0
* @since 4.1.0 The `$depth` parameter was added.
*
* @param array $classes The CSS classes that are applied to the menu item\'s `<li>` element.
* @param WP_Post $item The current menu item.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $depth Depth of menu item. Used for padding.
*/
$class_names = join( \' \', apply_filters( \'nav_menu_css_class\', array_filter( $classes ), $item, $args, $depth ) );
$class_names = $class_names ? \' class="\' . esc_attr( $class_names ) . \'"\' : \'\';
/**
* Filters the ID applied to a menu item\'s list item element.
*
* @since 3.0.1
* @since 4.1.0 The `$depth` parameter was added.
*
* @param string $menu_id The ID that is applied to the menu item\'s `<li>` element.
* @param WP_Post $item The current menu item.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $depth Depth of menu item. Used for padding.
*/
$id = apply_filters( \'nav_menu_item_id\', \'menu-item-\'. $item->ID, $item, $args, $depth );
$id = $id ? \' id="\' . esc_attr( $id ) . \'"\' : \'\';
$output .= $indent . \'<li\' . $id . $class_names .\'>\';
$atts = array();
$atts[\'title\'] = ! empty( $item->attr_title ) ? $item->attr_title : \'\';
$atts[\'target\'] = ! empty( $item->target ) ? $item->target : \'\';
$atts[\'rel\'] = ! empty( $item->xfn ) ? $item->xfn : \'\';
$atts[\'href\'] = ! empty( $item->url ) ? $item->url : \'\';
/**
* Filters the HTML attributes applied to a menu item\'s anchor element.
*
* @since 3.6.0
* @since 4.1.0 The `$depth` parameter was added.
*
* @param array $atts {
* The HTML attributes applied to the menu item\'s `<a>` element, empty strings are ignored.
*
* @type string $title Title attribute.
* @type string $target Target attribute.
* @type string $rel The rel attribute.
* @type string $href The href attribute.
* }
* @param WP_Post $item The current menu item.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $depth Depth of menu item. Used for padding.
*/
$atts = apply_filters( \'nav_menu_link_attributes\', $atts, $item, $args, $depth );
$attributes = \'\';
foreach ( $atts as $attr => $value ) {
if ( ! empty( $value ) ) {
$value = ( \'href\' === $attr ) ? esc_url( $value ) : esc_attr( $value );
$attributes .= \' \' . $attr . \'="\' . $value . \'"\';
}
}
/** This filter is documented in wp-includes/post-template.php */
$title = apply_filters( \'the_title\', $item->title, $item->ID );
/**
* Filters a menu item\'s title.
*
* @since 4.4.0
*
* @param string $title The menu item\'s title.
* @param WP_Post $item The current menu item.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param int $depth Depth of menu item. Used for padding.
*/
$title = apply_filters( \'nav_menu_item_title\', $title, $item, $args, $depth );
$item_output = $args->before;
$item_output .= \'<a\'. $attributes .\'>\';
$item_output .= $args->link_before . $title . $args->link_after;
$item_output .= \'</a>\';
$item_output .= $args->after;
/**
* Filters a menu item\'s starting output.
*
* The menu item\'s starting output only includes `$args->before`, the opening `<a>`,
* the menu item\'s title, the closing `</a>`, and `$args->after`. Currently, there is
* no filter for modifying the opening and closing `<li>` for a menu item.
*
* @since 3.0.0
*
* @param string $item_output The menu item\'s starting HTML output.
* @param WP_Post $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param stdClass $args An object of wp_nav_menu() arguments.
*/
$output .= apply_filters( \'walker_nav_menu_start_el\', $item_output, $item, $depth, $args );
}
} // END class Title_Sub_Menus
对我来说,这似乎有点混乱/奇怪,没有更简单或更直接的方法来做到这一点,所以这是一个可能的解决方案。希望有人能提供更直观的解决方案和解释。