Workaround for exclude_tree bug in wp_list_pages()

WordPress’s wp_list_pages() function includes a parameter that’s intended to let you exclude a Page and all of its descendants from your Page lists: ‘exclude_tree’. The idea is that if you pass wp_list_pages this parameter, e.g. by using wp_list_pages(’exclude_tree=1′), you can remove entire sections of your website from your Page lists, and new Pages in that section will be automatically excluded without you having to modify your code.

According to the wp_list_pages() documentation, if you want to exclude multiple sections of your website from your Page lists, you should be able to pass a comma-separated list of Page IDs, e.g. wp_list_pages(’exclude_tree=1,2,3′) and all of those Pages and all of their descendants should be omitted.

Note that using the ‘exclude’ parameter won’t give you this behaviour. If you use wp_list_pages(’exclude=1,2,3′), and Page #1 has descendants, then these descendants will be tacked onto the end of your Page lists in a way that bears no relation to their positions in your website’s heirarchy. You could manually exclude these descendants by adding their IDs to the list, but then when you create a new Page in this section of your website it will appear at the end of your Page lists, so this isn’t ideal.

So ‘exclude_tree’ is a useful additional parameter for wp_list_pages() to have.

Unfortunately, ‘exclude_tree’ doesn’t work: ’exclude_tree’ will only accept the first value in your comma-separated list of IDs, so it can’t currently be used to exclude multiple sections of websites from Page lists. This is a known bug, and will hopefully be fixed in a future release of WP, but in the meantime a workaround is needed.

As the ‘exclude’ parameter does work as intended, excluding every Page ID its given, what we need to do to emulate ‘exclude_tree’ is start with a list of Page IDs, generate a comma-separated list containing those IDs and the IDs of all of those Pages’ descendants, and then load that list into the wp_list_pages() ’exclude’ parameter. This code does just that:

$parent_pages_to_exclude = array(1,2,3);
foreach($parent_pages_to_exclude as $parent_page_to_exclude) {
if ($page_exclusions) { $page_exclusions .= ‘,’ . $parent_page_to_exclude; }
else { $page_exclusions = $parent_page_to_exclude; }
$descendants = get_pages(’child_of=’ . $parent_page_to_exclude);
foreach($descendants as $descendant) {
$page_exclusions .= ‘,’ . $descendant->ID;
}
}
wp_list_pages(’title_li=&sort_column=menu_order&exclude=’ . $page_exclusions);

Of course, you could use the Page Lists Plus plugin to achieve similar results without having to edit your code. To hard-code this behaviour into your theme files, though, use the code above.

Leave a Reply

You must be logged in to post a comment.