Alright, so I usually use wp_list_pages to create my menus. This usually works pretty well, but every now and then a project comes along that requires more than the functionality provided by the wp_list_pages function.
So maybe you want a menu that should have a nested sub menu when viewing a page and/or child to one of the “main pages”.
This could be done by passing a custom Walker to the wp_list_pages function.
class Custom_Walker_Page extends Walker_Page { function start_el(&$output, $page, $depth, $args, $current_page) { extract($args, EXTR_SKIP); $css_class = array(); $extra = ''; if ( !empty($current_page) ) { $_current_page = get_page( $current_page ); if ( ( isset($_current_page->ancestors) && in_array($page->ID, (array) $_current_page->ancestors) ) || ( $page->ID == $current_page ) || ( $_current_page && $page->ID == $_current_page->post_parent ) ) $css_class[] = 'sel'; if ( $page->ID == $current_page || in_array($page->ID, (array) $_current_page->ancestors) ) { $sub = $current_page; if( count($_current_page->ancestors) > 1 ) $sub = $_current_page->ancestors[0]; $extra = wp_list_pages('title_li=&echo=0&child_of=' . $sub ); if ( $extra ) $extra = '<ul class="sub">' . $extra . '</ul>'; } } $css_class = implode(' ', apply_filters('page_css_class', $css_class, $page)); $output .= '<li' (="" $css_class="" ?="" class="' . $css_class . '" :="" )="" .=""><a href="%27%20.%20get_page_link%28$page-%3EID%29%20.%20%27" title="' . esc_attr( wp_strip_all_tags( apply_filters( 'the_title', $page->post_title ) ) ) . '"><span>' . apply_filters( 'the_title', $page->post_title ) . '</span></a>'; $output .= $extra; } }
And then pass it to the wp_list_pages function:
$walker = new Custom_Walker_Page(); wp_list_pages( array( 'child_of' => $parent_id, 'depth' => 1, 'walker' => $walker) );
I guess this is pretty advanced stuff, so I have created some new categories. This post falls into the “Advanced” category.
Where do you place this class?
Your theme’s functions.php file would do fine!
WP doesn’t seem to be passing in the last argument ($current_page). I even checked wp-includes/nav-menu-template.php and the method has a mention of current_page in the comments, but no reference to it in the actual code.
This is to be used with wp_list_pages but it could be used with wp_nav_menu with some modification. This custom class extends Walker_Page but the default walker for wp_nav_menu is Walker_Nav_Menu. So you should look at that class, and perhaps extend that instead.
[…] Create a custom menu by creating your own Walker July 2010 4 comments 3 […]
I having a little problem following your code
‘
what does the (=”” mean as well as the ?=””
I am not that good with php but I cant find any information about this notation.
It could have something to do with the way the page is displaying the code
( $page->ID == $current_page )
I think should be
( $page->ID == $current_page )
Weird! Seems like > got turned into > in some cases. Just make sure that you don’t have any HTML-entities in your PHP-code and you should be fine!
This post is really handy as there is not much infomation on this subject.
is this section correct?
I am having a bit of difficulty understanding it
‘
I guess its a shorthand if but the statement
(=”” $css_class=””
is not clear to me what it is doing.
Is the code correct or has this gotten mixed up as well?
Thank you for responding.
Awesome work! Thank you so much for sharing Vincent.
Is it possible to alter the default Walker_Nav_Menu, and impact theme output through a plugin only? No alteration to core WordPress, no functions.php or theme changes…just a plugin that would force a new walker method?