Extending the WordPress Walker Class

Posted on

Many of us don’t realise that when calling wp_list_pages, the actual output is generated by the WordPress Walker Class. And to tell you the truth, I have always dreaded going into this Walker Class, simply because I didn’t really understand what I would need it for and how to go about to changing it.

But earlier this week, I had a request to implement something in a website and after a lot of searching, extending the WordPress Walker Class seemed the only thing possible.

The Problem

Walker ClassFor a set of four Pages the client wanted to show the direct Children of those Pages at the bottom. However, each Child had to show a different image. The names of the Children Pages are the same for each of the four Parent Pages: Past, Current and Future.
The easiest solution would be to take the Page IDs of each of the Children and style them with CSS. But that is hardly a solution that will stand the test of time, so I wanted something more robust.

The Solution

I found the solution with the help of MDBitz Development Resources. They explain about the Walker Class that

the Walker class can be extended to customize your page lists with unique and custom functionality

Just what I needed! But if you look at the Codex, you can imagine that there are not an awful lot of people that want to dive in there!

Fortunately they explain things further in plain English:

the walker is what creates the end HTML that will be displayed when calling a function. Without knowing it by calling the wp_list_pages function you are actually having the Walker_Page class render the final HTML based on your provided options.

The Walker Class consists of 5 functions: walk, start_lvl, end_lvl, start_el and end_el.
To explain it further with wp_list_pages in mind, the first function, walk, basically starts the output needed to make the unordered list and the list items inside. The function start_lvl is called when the element is a child of the previous element and the output of each element starts with start_el.

As you can see in the source-code of wp-includes/classes.php, start_lvl normally outputs the start of the unordered list and gives it the class children and end_lvl closes the unordered list.

Within those two start_el and end_el open and close the list-item and output all the html necessary to show the title, link to it, etc. in between.

The Code

With the above in mind, there is no need to write a completely new Walker Class, instead I can extend the existing. Specifically for my problem, the function I need to adapt is the output of the list-item, in other words I only need to adapt the start_el function.

I need to give each list-item the class of its slug instead of the normal output that consists of page_item page-item-ID and more of that.

As MDBitz explains to start extending the Walker Class you need to start by adding this to your functions.php file:

class Walker_Child_Classes extends Walker_page {
  // code 
}

The Walker_Child_Classes bit you can adapt to reflect what you are going to do.

My whole Walker Class looks like this:

// GIVE CHILDREN LIST ITEMS CLASS OF CHILD
// freely adapted from http://resources.mdbitz.com/2010/08/creating-a-wordpress-custom-page-walker/
class Walker_Child_Classes extends Walker_page {
  	function start_el(&$output, $page, $depth, $args, $current_page) {
			if ( $depth )
				$indent = str_repeat("\t", $depth);
			else
				$indent = '';

			extract($args, EXTR_SKIP);

			$output .= $indent . '<li class="' . apply_filters( 'the_title', $page->post_name, $page->ID ) . '"><a href="' . get_page_link($page->ID) . '" title="' . esc_attr( wp_strip_all_tags( apply_filters( 'the_title', $page->post_title, $page->ID ) ) ) . '">' . $link_before . apply_filters( 'the_title', $page->post_title, $page->ID ) . $link_after . '</a>';
		}
}

The change I made is visible on line 12. Instead of the normal class ($css_class) I give these particular list-items the slug class: 'the_title', $page->post_name, $page->ID.

To make this new Walker Class visible, you need to do one last thing: include it in the wp_list_pages call in your Page Template.

<ul class="timeline">
	<?php 
	//freely adapted from http://resources.mdbitz.com/2010/08/creating-a-wordpress-custom-page-walker/
	$sWalker = new Walker_Child_Classes();
	wp_list_pages( array( 'title_li' => null, 'walker' => $sWalker, 'sort_column' => 'menu_order', 'sort_order' => 'DESC', 'child_of' => $post->ID ) );
	?>
</ul><!-- .timeline -->

By adding the new Walker Class to my wp_list_pages call, I am telling WordPress not to use the default output, but instead to use the class that I made specifically for this Page Template.

The Result

Now that the list items actually receive their resp. slugs as class, I can style the list-items to my liking using the Past, Current and Future images for them.

This is what the output looks like:
Result of Extending the Walker Class

Have you ever worked with the WordPress Walker Class? Let us know about your experience in the comments!

6 comments on “Extending the WordPress Walker Class

  1. comment on July 28 that was a false positive caught by Firewall plugin:

    Nice explanation, Piet. I had no idea Walker was what rendered the HTML on wp_list_pages. I always thought it was some kind of exotic side element for use only by developers who did exotic things with it.

    • Thanks for your comment Gumaraphous, I also wonder why the Codex doesn’t explain it better. Once you understand the class, it becomes very valuable.

  2. Hmmm. I’ve been messing with this for a couple hours – I’m on WP 3.3.1 and when I try to extend the walker class I get

    Fatal error: Using $this when not in object context in /home/content/m/y/m/mym0ney/html/wp-includes/class-wp-walker.php on line 185

    :(

    • Hi Andy, sorry to hear that it is not yet working for you. But I hope you understand that the only thing I can say about your error is where $this comes from?
      If you want me or others to take a look at your code, why don’t you post it on Github or sth?

Comments are closed.