wp_list_pages()WP 1.5.0

Retrieve or display list of pages (or hierarchical post type items) in list (li) format.

Used By: wp_page_menu()
1 time — 0.014449 sec (extremely slow) | 50000 times — 213.16 sec (extremely slow) | PHP 7.1.2, WP 4.7.3
Hooks from the function

Return

null|String. Void if 'echo' argument is true, HTML list of pages if 'echo' is false.

Usage

wp_list_pages( $args );
$args(array|string)

Array or string of arguments to generate a list of pages. See get_pages() for additional arguments.

Default: ''

  • child_of(int)
    Display only the sub-pages of a single page by ID.
    Default: 0 (all pages)

  • authors(string)
    Comma-separated list of author IDs.
    Default: empty (all authors)

  • date_format(string)
    PHP date format to use for the listed pages. Relies on the 'show_date' parameter.
    Default: value of 'date_format' option

  • depth(int)
    Number of levels in the hierarchy of pages to include in the generated list. Accepts -1 (any depth), 0 (all pages), 1 (top-level pages only), and n (pages to the given n depth).

  • echo(true|false)
    Whether or not to echo the list of pages.
    Default: true

  • exclude(string)
    Comma-separated list of page IDs to exclude.
    Default: ''

  • include(array)
    Comma-separated list of page IDs to include.
    Default: ''

  • link_after(string)
    Text or HTML to follow the page link label.
    Default: null

  • link_before(string)
    Text or HTML to precede the page link label.
    Default: null

  • post_type(string)
    Post type to query for.
    Default: 'page'

  • post_status(string|array)
    Comma-separated list or array of post statuses to include.
    Default: 'publish'

  • show_date(string)
    Whether to display the page publish or modified date for each page. Accepts 'modified' or any other value. An empty value hides the date.
    Default: ''

  • sort_column(string)
    Comma-separated list of column names to sort the pages by. Accepts 'post_author', 'post_date', 'post_title', 'post_name', 'post_modified', 'post_modified_gmt', 'menu_order', 'post_parent', 'ID', 'rand', or 'comment_count'.
    Default: 'post_title'

  • title_li(string)
    List heading. Passing a null or empty value will result in no heading, and the list will not be wrapped with unordered list <ul> tags.
    Default: 'Pages'

  • item_spacing(string)
    Whether to preserve whitespace within the menu's HTML. Accepts 'preserve' or 'discard'.
    Default: 'preserve'

  • walker(Walker)
    Walker instance to use for listing pages.
    Default: empty which results in a Walker_Page instance being used

Examples

0

#1 Let's remove the title of the list by removing the title_li parameter.

Keep in mind that ul tags will also be deleted and must be specified separately:

<ul>
	<?php wp_list_pages('title_li='); ?>
</ul>
0

#2 Change the header

Change the title to "Poetry", wrap it in the HTML tag <h2> and list only the permanent pages with IDs 9, 5 and 23:

<ul>
	<?php wp_list_pages( 'include=5,9,23&title_li=<h2>' . __('Poetry') . '</h2>' ); ?>
</ul>
0

#3 Sorting by ordinal number [auto-translate]

Let's sort the list according to the ordinal numbers indicated on the "permanent pages" editing page:

<ul>
	<?php wp_list_pages('sort_column=menu_order'); ?>
</ul>
0

#4 Let's remove the "Pages" header from the list: [auto-translate]

<ul>
  <?php wp_list_pages('sort_column=menu_order&title_li='); ?>
</ul>
0

#5 Sorting by date of creation [auto-translate]

Let's display the list sorted by date of creation of the "permanent page" and show the date next to each link:

<ul>
	<?php wp_list_pages('sort_column=post_date&show_date=created'); ?>
</ul>
0

#6 Excluding pages [auto-translate]

Using the parameter exclude we will exclude pages with IDs 17,38:

<ul>
	<?php wp_list_pages('exclude=17,38' ); ?>
</ul>
0

#7 List of only pages with the specified IDs [auto-translate]

Using the parameter include, create a list of only pages with IDs 35, 7, 26 and 13:

<ul>
	<?php wp_list_pages('include=7,13,26,35&title_li=<h2>' . __('Pages') . '</h2>' ); ?>
</ul>
0

#8 Let's display the list of child pages [auto-translate]

Using the following example, you can display in the sidebar (or elsewhere) a list of child pages (subpages) of the permanent page you are currently on. To do this, use parameter child_of and check if there are any child pages for the current page (let's try to get child pages into variable $children, and if it works, let's output a list):

<?php
$children = wp_list_pages( 'title_li=&child_of=' . $post->ID . '&echo=0' );

if( $children ){
	?>
	<ul>
		<?php echo $children; ?>
	</ul>
	<?php
}
?>
0

#9 Static list of child pages [auto-translate]

Let's go further and display a list of child pages and make this list remain when we go to one of these child pages (i.e. for child pages, we get a list of single-level pages):

<?php
if( $post->post_parent ){
	$children = wp_list_pages( "title_li=&child_of=" . $post->post_parent . "&echo=0" );
}
else {
	$children = wp_list_pages( "title_li=&child_of=" . $post->ID . "&echo=0" );
}

if( $children ){
	?>
	<ul>
		<?php echo $children; ?>
	</ul>
	<?php
}
?>

This example can be used in the sidebar (sidebar), but you should understand that it checks first if the current page has a parent page, if it exists then the list of single-level pages is displayed, if there is no parent page then the list of child pages is displayed. So we will have a closed list for the top-level pages on all pages.

0

#10 Static list of child pages (alternative) [auto-translate]

An alternative version of the previous example.

This example can also be used in the sidebar, it will output:

  • when you are on the home page, all of the top-level "permanent pages" will be shown;

  • When you are on a top-level "permanent page" that has no child pages, all the same top-level "permanent pages" will be shown;

  • When you are on a top-level "permanent page" that has child pages, those child pages and their child pages will be shown;

  • when you are on a child page of the top-level "permanent page" (the second-level page), the child pages of the top-level "permanent page" (i.e., the child pages of the parent page) will be shown.
$output = wp_list_pages( 'echo=0&depth=1&title_li=<h2>Top level pages</h2>' );

if( is_page() ){
	$page = $post->ID;

	if( $post->post_parent ){
		$page = $post->post_parent;
	}

	$children = wp_list_pages( 'echo=0&child_of=' . $page . '&title_li=' );

	if( $children ){
		$output = wp_list_pages( 'echo=0&child_of=' . $page . '&title_li=<h2>Child Pages</h2>' );
	}
}

echo $output;
0

#11 List of pages, only if there is one [auto-translate]

A list of child pages that will only be shown if the "permanent page" has child pages. The child pages will be shown both on the parent "permanent page" and on the child pages themselves. The difference from the previous example is that the name of the parent "permanent page" is in the header of the list:

<?php
if( $post->post_parent ){
	$children = wp_list_pages( "title_li=&child_of=" . $post->post_parent . "&echo=0" );
	$titlenamer = get_the_title( $post->post_parent );
}

else{
	$children = wp_list_pages( "title_li=&child_of=" . $post->ID . "&echo=0" );
	$titlenamer = get_the_title( $post->ID );
}

if( $children ){
	?>

	<h2> <?php echo $titlenamer; ?> </h2>
	<ul>
		<?php echo $children; ?>
	</ul>

	<?php
}
?>
0

#12 All child pages on pages of any nesting level [auto-translate]

This example shows how to get all child pages, on pages of any nesting level:

<?php
if( ! $post->post_parent ){
	// get child pages, for the "permanent page" of the top level
	$children = wp_list_pages( "title_li=&child_of=" . $post->ID . "&echo=0" );
}
else{
	// get the child pages if we are on the first level child page.
	//$children = wp_list_pages("title_li=&child_of=".$post->post_parent."&echo=0");

	if( $post->ancestors ){
		// now get the ID of the very first page (the oldest one)
		// wp collects IDs in reverse order, so the "first" page will be the last
		$ancestors = end( $post->ancestors );
		$children = wp_list_pages( "title_li=&child_of=" . $ancestors . "&echo=0" );
		// that's it, now we will always have a list of all child pages,
		// whatever nesting level we are on.
	}
}

if( $children ){
	?>
	<ul>
		<?php echo $children; ?>
	</ul>
	<?php
}
?>
0

#13 The tree of child pages of the specified page [auto-translate]

Since there is no way to tell wp_list_pages to output the tree (all nesting levels) of pages of a particular page (e.g. pages with ID 93), we can use get_pages() to do this trick:

<?php
// Use wp_list_pages to show the parent and all child pages
// (including all nested ones)
$pages = get_pages( 'child_of=93' );
$parent = 25;
if( $pages ){
	$pageids = [];

	foreach( $pages as $page ){
		$pageids[] = $page->ID;
	}

	wp_list_pages( [
		'title_li' => 'Parent page tree: ' . $parent,
		'include'  => $parent . ',' . implode( ',', $pageids ),
	] );
}
?>
0

#14 Labeling and Styling page lists [auto-translate]

By default, wp_list_pages() creates a list of this construction:

<li class="pagenav">Pages
	<ul>
		<li class="page_item page-item-4"></li>
		<li class="page_item page-item-5"></li>
		...
	</ul>
</li>

If we remove the title by putting an empty parameter title_li=, the view becomes like this:

<li class="page_item page-item-4"></li>
<li class="page_item page-item-5"></li>
...

Another way of putting it is this:

<li class="pagenav">
Pages [title_li]
  <ul>
	<!-- The list starts here if the 'title_li' parameter is blank -->
	<li class="page-item-2 page_item current_page_ancestor current_page_parent">
	  [parent of the current page]
		  <ul>
			<li class="page-item-21 page_item current_page_item">[current page]</li>
		  </ul>
	</li>
	<li class="page-item-3 page_item">[other pages]</li>
  </ul>
</li>

All li tags created with function wp_list_pages() are marked with CSS class page_item. When a page you are on appears in the list, another class current_page_parent is added to the li element of the list.

Thus, the list can be "colored" with the following CSS selectors:

.pagenav { ... } /* the main ul tag class that wraps the entire list */
.page-item-2 { ... } /* element related to page with ID 2 */
.page_item { ... } /* any list item */
.current_page_item { ... } /* current page */
.current_page_parent { ... } /* the parent page of the current page */
.current_page_ancestor { ... } /* any page either related to the current page (parent or daughter.) */

To achieve a global effect on list items, use the following selectors:

.pagenav  ul ul,
.pagenav .current_page_item ul ul,
.pagenav .current_page_ancestor ul ul,
.pagenav .current_page_ancestor .current_page_item ul ul,
.pagenav .current_page_ancestor .current_page_ancestor ul ul {
	display: none;
}

.pagenav .current_page_item ul,
.pagenav .current_page_ancestor ul,
.pagenav .current_page_ancestor .current_page_item ul,
.pagenav .current_page_ancestor .current_page_ancestor ul,
.pagenav .current_page_ancestor .current_page_ancestor .current_page_item ul,
.pagenav .current_page_ancestor .current_page_ancestor .current_page_ancestor ul {
	display: block;
}
0

#15 List of related or child pages to the current page [auto-translate]

<?php
// if it is a child page
if( $post->post_parent ){

	// collect related pages
	$relations = get_post_ancestors( $post->ID );

	// get child pages (if any)
	$result = $wpdb->get_results( "SELECT ID FROM wp_posts WHERE post_parent = $post->ID AND post_type='page'" );

	// if the child pages of this page turned out to be
	// get them merged with their relatives
	foreach( $result as $page_id ){
		$relations[] = $page_id->ID;
	}

	// add the current page to the related pages
	$relations[] = $post->ID;

	// make a comma-separated ID list of related, child and current
	$relations_string = implode( ",", $relations );

	// get the list using the include parameter
	$sidelinks = wp_list_pages( "title_li=&echo=0&include=" . $relations_string );
}
// if it is not a child page
else {
	// show only child pages one level
	$sidelinks = wp_list_pages( "title_li=&echo=0&depth=1&child_of=" . $post->ID );
}

if( $sidelinks ){
	?>
	<h2><?php the_title(); ?></h2>
	<ul>
		<?php // display links in <li> tags
		echo $sidelinks; ?>
	</ul>
	<?php
}
?>
0

#16 Using an arbitrary record type (other than page) [auto-translate]

If the site has an arbitrary record type with a tree structure, wp_list_pages() can be used to display such records as well.

In general, all of the above examples will work for this case as well, the only thing you need to change is the type of record the function will work with.

The record type is specified in the post_type parameter:

wp_list_pages( [
  'post_type'=>'portfolio',
  'title_li'=> __('Portfolio')
] );

Notes

  • See: get_pages()
  • Global. WP_Query. $wp_query WordPress Query object.

Changelog

Since 1.5.0 Introduced.
Since 4.7.0 Added the item_spacing argument.

wp_list_pages() code WP 6.5.2

function wp_list_pages( $args = '' ) {
	$defaults = array(
		'depth'        => 0,
		'show_date'    => '',
		'date_format'  => get_option( 'date_format' ),
		'child_of'     => 0,
		'exclude'      => '',
		'title_li'     => __( 'Pages' ),
		'echo'         => 1,
		'authors'      => '',
		'sort_column'  => 'menu_order, post_title',
		'link_before'  => '',
		'link_after'   => '',
		'item_spacing' => 'preserve',
		'walker'       => '',
	);

	$parsed_args = wp_parse_args( $args, $defaults );

	if ( ! in_array( $parsed_args['item_spacing'], array( 'preserve', 'discard' ), true ) ) {
		// Invalid value, fall back to default.
		$parsed_args['item_spacing'] = $defaults['item_spacing'];
	}

	$output       = '';
	$current_page = 0;

	// Sanitize, mostly to keep spaces out.
	$parsed_args['exclude'] = preg_replace( '/[^0-9,]/', '', $parsed_args['exclude'] );

	// Allow plugins to filter an array of excluded pages (but don't put a nullstring into the array).
	$exclude_array = ( $parsed_args['exclude'] ) ? explode( ',', $parsed_args['exclude'] ) : array();

	/**
	 * Filters the array of pages to exclude from the pages list.
	 *
	 * @since 2.1.0
	 *
	 * @param string[] $exclude_array An array of page IDs to exclude.
	 */
	$parsed_args['exclude'] = implode( ',', apply_filters( 'wp_list_pages_excludes', $exclude_array ) );

	$parsed_args['hierarchical'] = 0;

	// Query pages.
	$pages = get_pages( $parsed_args );

	if ( ! empty( $pages ) ) {
		if ( $parsed_args['title_li'] ) {
			$output .= '<li class="pagenav">' . $parsed_args['title_li'] . '<ul>';
		}
		global $wp_query;
		if ( is_page() || is_attachment() || $wp_query->is_posts_page ) {
			$current_page = get_queried_object_id();
		} elseif ( is_singular() ) {
			$queried_object = get_queried_object();
			if ( is_post_type_hierarchical( $queried_object->post_type ) ) {
				$current_page = $queried_object->ID;
			}
		}

		$output .= walk_page_tree( $pages, $parsed_args['depth'], $current_page, $parsed_args );

		if ( $parsed_args['title_li'] ) {
			$output .= '</ul></li>';
		}
	}

	/**
	 * Filters the HTML output of the pages to list.
	 *
	 * @since 1.5.1
	 * @since 4.4.0 `$pages` added as arguments.
	 *
	 * @see wp_list_pages()
	 *
	 * @param string    $output      HTML output of the pages list.
	 * @param array     $parsed_args An array of page-listing arguments. See wp_list_pages()
	 *                               for information on accepted arguments.
	 * @param WP_Post[] $pages       Array of the page objects.
	 */
	$html = apply_filters( 'wp_list_pages', $output, $parsed_args, $pages );

	if ( $parsed_args['echo'] ) {
		echo $html;
	} else {
		return $html;
	}
}