wp_list_pages()
云策文档标注
概述
wp_list_pages() 是 WordPress 核心函数,用于检索或显示页面(或分层文章类型项目)的列表,以 HTML 列表(li)格式输出。它基于 get_pages() 查询页面,并支持丰富的参数来控制列表的生成和样式。
关键要点
- 函数返回 void 或 string:当 echo 参数为 true 时直接输出 HTML,为 false 时返回 HTML 字符串。
- 支持多种参数:包括 child_of、depth、exclude、include、sort_column、title_li、post_type 等,用于筛选和排序页面。
- 可应用于分层文章类型:不仅限于默认的 'page' 类型,任何 hierarchical 的自定义文章类型均可使用。
- 自动添加 CSS 类:如 .page_item、.current_page_item、.current_page_parent 等,便于样式定制。
- 包含两个过滤器钩子:wp_list_pages 用于过滤输出,wp_list_pages_excludes 用于过滤排除的页面 ID。
代码示例
// 基本用法:显示页面列表
wp_list_pages();
// 显示子页面列表,并设置标题
wp_list_pages( array(
'child_of' => $post->ID,
'title_li' => '<h2>子页面</h2>'
) );
// 排除特定页面,并自定义排序
wp_list_pages( array(
'exclude' => '1,2,3',
'sort_column' => 'post_date',
'sort_order' => 'desc'
) );
// 用于自定义文章类型
$args = array(
'post_type' => 'portfolio',
'title_li' => __( '作品集', 'textdomain' )
);
wp_list_pages( $args );注意事项
- title_li 参数控制列表标题:设置为空字符串可隐藏标题并移除外层 ul 标签。
- child_of 和 hierarchical 参数需注意:当 hierarchical 为 false 且 child_of 也为 false 时,两者均被忽略。
- 使用 include 参数时:不能与 child_of、parent、exclude、meta_key、meta_value 或 hierarchical 同时使用。
- 版本兼容性:item_spacing 参数在 WordPress 4.7.0 中引入,用于控制 HTML 中的空白保留。
原文内容
Retrieves or displays a list of pages (or hierarchical post type items) in list (li) format.
Description
See also
Parameters
$argsarray|stringoptional-
Array or string of arguments to generate a list of pages. See get_pages() for additional arguments.
child_ofintDisplay only the sub-pages of a single page by ID. Default 0 (all pages).authorsstringComma-separated list of author IDs. Default empty (all authors).date_formatstringPHP date format to use for the listed pages. Relies on the'show_date'parameter.
Default is the value of'date_format'option.depthintNumber 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). Default 0.echoboolWhether or not to echo the list of pages. Default true.excludestringComma-separated list of page IDs to exclude. Default empty.includearrayComma-separated list of page IDs to include. Default empty.link_afterstringText or HTML to follow the page link label. Default null.link_beforestringText or HTML to precede the page link label. Default null.post_typestringPost type to query for. Default'page'.post_statusstring|arrayComma-separated list or array of post statuses to include. Default'publish'.show_datestringWhether to display the page publish or modified date for each page. Accepts'modified'or any other value. An empty value hides the date. Default empty.sort_columnstringComma-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_listringList 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_spacingstringWhether to preserve whitespace within the menu’s HTML. Accepts'preserve'or'discard'.
Default'preserve'.walkerWalkerWalker instance to use for listing pages. Default empty which results in a Walker_Page instance being used.
More Arguments from get_pages( … $args )
Array or string of arguments to retrieve pages.
child_ofintPage ID to return child and grandchild pages of. Note: The value of$hierarchicalhas no bearing on whether$child_ofreturns hierarchical results. Default 0, or no restriction.sort_orderstringHow to sort retrieved pages. Accepts'ASC','DESC'. Default'ASC'.sort_columnstringWhat columns to sort pages by, comma-separated. Accepts'post_author','post_date','post_title','post_name','post_modified','menu_order','post_modified_gmt','post_parent','ID','rand','comment*count'.
'post*'can be omitted for any values that start with it.
Default'post_title'.hierarchicalboolWhether to return pages hierarchically. If false in conjunction with$child_ofalso being false, both arguments will be disregarded.
Default true.excludeint[]Array of page IDs to exclude.includeint[]Array of page IDs to include. Cannot be used with$child_of,$parent,$exclude,$meta_key,$meta_value, or$hierarchical.meta_keystringOnly include pages with this meta key.meta_valuestringOnly include pages with this meta value. Requires$meta_key.authorsstringA comma-separated list of author IDs.parentintPage ID to return direct children of. Default -1, or no restriction.exclude_treestring|int[]Comma-separated string or array of page IDs to exclude.numberintThe number of pages to return. Default 0, or all pages.offsetintThe number of pages to skip before returning. Requires$number.
Default 0.post_typestringThe post type to query. Default'page'.post_statusstring|arrayA comma-separated list or array of post statuses to include.
Default'publish'.
Source
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;
}
}
Hooks
- apply_filters( ‘wp_list_pages’, string $output, array $parsed_args, WP_Post[] $pages )
-
Filters the HTML output of the pages to list.
- apply_filters( ‘wp_list_pages_excludes’, string[] $exclude_array )
-
Filters the array of pages to exclude from the pages list.
Skip to note 18 content
Codex
List Sub-Pages
Versions prior to WordPress 2.0.1:
Put this inside the
the_post()section of thepage.phptemplate of your WordPress theme afterthe_content(), or put it in a copy of the page.php template that you use for pages that have sub-pages:<ul> '', 'child_of' => $id, 'show_date' => 'modified', 'date_format' => $date_format ) ); ?> </ul>This example does not work with WordPress 2.0.1 or newer if placed in a page template because the global
$idis not set. Use the following code instead.WordPress 2.0.1 or newer:
NOTE: Requires an HTML list tag (either
<ul>or<ol>) even if there are no subpages. Keep this in mind if you are using CSS to style the list.<ul> '', 'child_of' => $post->ID, 'show_date' => 'modified', 'date_format' => $date_format ) ); ?> </ul>The following example will generate a list only if there are child pages (pages that designate the current page as a parent) for the current page:
ID.'&echo;=0' ); if ( $children) : ?> <ul> </ul>Skip to note 19 content
Codex
Hiding or Changing the List Heading
The default heading of the list (“Pages”) of Pages generated by
wp_list_pagescan be hidden by passing a null or empty value for thetitle_liparameter. The following example displays no heading text above the list.<ul> '' ) ); ?> </ul>In the following example, only Pages with IDs 9, 5, and 23 are included in the list and the heading text has been changed to the word “Poetry”, with a heading style of :
<ul> array( 5, 9, 23 ), 'title_li' => '<h2>' . __('Poetry') . '</h2>' ) ); ?> </ul>Skip to note 20 content
Codex
List members of a custom post type
If a given custom post type is hierarchical in nature, then
wp_list_pages()can be used to list the member of that custom post type. In this example the custom post type Portfolio is listed:$args = array( 'post_type' => 'portfolio', 'title_li' => __( 'Portfolio', 'textdomain' ) ); wp_list_pages( $args );Skip to note 21 content
PHPanos
I didn’t see anywhere that you could pass a sort_order argument. So I think it would be good to make it more obvious by including it in the args list.
This code orders pages by post_date and sorts the pages by descending order so that you will get the latest pages first.
wp_list_pages(array('sort_column' => 'post_date', 'sort_order' => 'desc'));Skip to note 22 content
Codex
List subpages even if on a subpage
The above examples will only show the children from the parent page, but not when actually on a child page. This code will show the child pages, and only the child pages, when on a parent or on one of the children.
This code will not work if placed after a widget block in the sidebar.
post_parent ) { $children = wp_list_pages( array( 'title_li' => '', 'child_of' => $post->post_parent, 'echo' => 0 ) ); } else { $children = wp_list_pages( array( 'title_li' => '', 'child_of' => $post->ID, 'echo' => 0 ) ); } if ( $children ) : ?> <ul> </ul>As an alternative, this code in a
sidebar.php, displays only top level pages, but when viewing a page that has children (or is a child) it displays only children of that parent.When visiting main page, all top level pages are listed in the sidebar.
When visiting a top level page with no children, all top level pages are listed.
When visiting a top level page with children, just the children pages, and descendant pages, are listed.
When visiting a child page, just the children, and descendant pages, of that parent, are listed.
$output = wp_list_pages( array( 'echo' => 0, 'depth' => 1, 'title_li' => '<h2>' . __( 'Top Level Pages', 'textdomain' ) . '</h2>' ) ); if ( is_page() ) { $page = $post->ID; if ( $post->post_parent ) { $page = $post->post_parent; } $children = wp_list_pages( array( 'echo' => 0, 'child_of' => $page, 'title_li' => '' ) ); if ( $children ) { $output = wp_list_pages( array( 'echo' => 0, 'child_of' => $page, 'title_li' => '<h2>' . __( 'Child Pages', 'textdomain' ) . '</h2>' ) ); } } echo $output;Page list that only displays if child (sub) pages exist, displays page list of subpages on the parent page AND on the child pages
However this code keeps the parent page name in the title which makes it different from the previous example.
post_parent ) { $children = wp_list_pages( array( 'title_li' => '', 'child_of' => $post->post_parent, 'echo' => 0 ) ); $title = get_the_title( $post->post_parent ); } else { $children = wp_list_pages( array( 'title_li' => '', 'child_of' => $post->ID, 'echo' => 0 ) ); $title = get_the_title( $post->ID ); } if ( $children ) : ?> <h2></h2> <ul> </ul>Skip to note 23 content
Codex
Markup and styling of page items
By default,
wp_list_pages()generates a nested, unordered list of WordPress pages created with the Write > Page admin panel. You can remove the outermost item (li.pagenav) and list (ul) by setting thetitle_liparameter to an empty string.All list items (
li) generated bywp_list_pages()are marked with the classpage_item. Whenwp_list_pages()is called while displaying a page, the list item for that Page is given the additional classcurrent_page_item.<li class="pagenav"> Pages [title_li] <ul> <!-- Output starts here if 'title_li' parameter is empty --> <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"> [the current Page] </li> </ul> </li> <li class="page-item-3 page_item"> [another Page] </li> </ul> </li>They can be styled with CSS selectors:
[html]
.pagenav { … } /* the outermost list item; contains whole list */
.page-item-2 { … } /* item for Page ID 2 */
.page_item { … } /* any Page item */
.current_page_item { … } /* the current Page */
.current_page_parent { … } /* parent of the current Page */
.current_page_ancestor { … } /* any ancestor of the current Page */
In order to achieve an accordion menu effect for instance, the following CSS can be used:
.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;
}
[/html]
Skip to note 24 content
Codex
Exclude Pages from List
Use the
excludeparameter to hide certain pages from the list to be generated bywp_list_pages.<ul> </ul>Skip to note 25 content
Codex
List all top-level pages and subpages only of this parent
The following lists all top-level pages and
if on a top level page – children of only this page
if on a subpage – its siblings but not children of other top pages
$ancestor_id = 1843; // you want to change this $descendants = get_pages( array( 'child_of' => $ancestor_id ) ); $incl = ''; foreach ( $descendants as $page ) { if ( ( $page->post_parent == $ancestor_id ) || ( $page->post_parent == $post->post_parent ) || ( $page->post_parent == $post->ID ) ) { $incl .= $page->ID . ","; } } ?> <ul> $ancestor_id, 'include' => $incl, 'link_before' => '', 'title_li' => '', 'sort_column' => 'menu_order' ) ); ?> </ul>Skip to note 26 content
Lance Cleveland
*Custom Post/Page Types*
Custom page types will require the hierarchical property to be set to true in the register_post_type (see https://developer.wordpress.org/reference/functions/register_post_type/) parameter list.
By default the only WordPress post type that is hierarchical is the ‘page’ type.
Only hierarchical post types are returned by this function.
Skip to note 27 content
Codex
List Pages by Page Order
The following example lists the pages in the order defined by the
Ordersetting for each page in the Pages→Edit panel.<ul> 'menu_order' ) ); ?> </ul>If you wanted to sort the list by page order and display the word “Prose” as the list heading (in h2 style) on a sidebar, you could add the following code to the sidebar.php file:
<ul> ' . __( 'Prose' ) . '</h2>' ); ?> </ul>Using the following piece of code, the pages will display without heading and in page order:
<ul> </ul>Skip to note 28 content
Codex
Sort Pages by Post Date
This example displays Pages sorted by (creation) date, and shows the date next to each page list item.
<ul> </ul>Skip to note 29 content
Codex
Include Pages in List
To include only certain pages in the list, for instance, pages with ID numbers 35, 7, 26 and 13, use the
includeparameter.<ul> ' . __( 'Pages' ) . '</h2>' ); ?> </ul>Skip to note 30 content
Codex
List whole subpages
This is how to get the whole subpages list
if( ! $post->post_parent ) { // Will display the subpages of this top level page. $children = wp_list_pages( array( 'title_li' => '', 'child_of' => $post->ID, 'echo' => 0 ) ); } else { if ( $post->ancestors ) { /* * Now you can get the the top ID of this page. WordPress is putting the ids DESC, * thats why the top level ID is the last one. */ $ancestors = get_post_ancestors( $this_page ); $children = wp_list_pages( array( 'title_li' => '', 'child_of' => $ancestors, 'echo' => 0 ) ); } } if ( $children ) : ?> <ul> </ul>Skip to note 31 content
Codex
List parent page and all descendant pages
Since there’s no way to tell
wp_list_pagesto display a particular parent tree (parent and all generations displayes) this example usesget_pagesto get all the descendants for a parent, then usewp_list_pagesto display the ‘family tree’.$parent ); $pages = get_pages( $args ); if ( $pages ) { $pageids = array(); foreach ( $pages as $page ) { $pageids[] = $page->ID; } $args = array( 'title_li' => sprintf( __( 'Tree of Parent Page %s', 'textdomain' ), $parent ), 'include' => $parent . ',' . implode( ",", $pageids ) ); wp_list_pages( $args ); } ?>Skip to note 32 content
Codex
List current Page with its ancestors and children
This example will list current page, ancestors of current page, and children of current page, Since
child_ofdisplays all children,wpdbis used instead, along with include to not display everything ‘and the kitchen sink’.// If the post has a parent. if( $post->post_parent ) { // Collect ancestor pages. $relations = get_post_ancestors( $post->ID ); // Get child pages. $result = $wpdb->get_results( $wpdb->prepare( "SELECT ID FROM wp_posts WHERE post_parent = %s AND post_type = %s", $post->ID, 'page' ) ); if ( $result ) { foreach ( $result as $page ) { array_push( $relations, $page->ID ); } } // Add current post to pages. array_push( $relations, $post->ID ); // Get comma delimited list of children and parents and self. $relations_string = implode( ",",$relations ); // Use include to list only the collected pages. $sidelinks = wp_list_pages( array( 'title_li' => '', 'echo' => 0, 'include' => $relations_string ) ); } else { // Display only main level and children. $sidelinks = wp_list_pages( array( 'title_li' => '', 'echo' => 0, 'depth' => 1, 'child_of' => $post->ID ) ); } if ( $sidelinks ) : ?> <h2></h2> <ul> tags. echo $sidelinks; ?> </ul>Skip to note 33 content
Codex
List topmost ancestor and its immediate children
This method will show the topmost ancestor of the current page as well as the topmost ancestor’s immediate children. This can be used for clean secondary subnavigation.
First, create the following function (preferably in
functions.php, assuming this is for a theme):if ( ! function_exists( 'wpdocs_get_post_top_ancestor_id' ) ) { /** * Gets the id of the topmost ancestor of the current page. * * Returns the current page's id if there is no parent. * * @return int ID of the top ancestor page. */ function wpdocs_get_post_top_ancestor_id() { if ( ! $post = get_post() ) { return; } $top_ancestor = $post->ID; if ( $post->post_parent ) { $ancestors = array_reverse( get_post_ancestors( $post->ID ) ); $top_ancestor = $ancestors[0]; } return $top_ancestor; } } // Exists.Next, add the following code to your theme (wherever you want the menu to appear):
<ul class="clearfix"> '', 'include' => wdocs_get_post_top_ancestor_id() ) ); wp_list_pages( array( 'title_li' => '', 'depth' => 1, 'child_of' => wpdocs_get_post_top_ancestor_id() ) ); ?> </ul>Skip to note 34 content
Codex
List the Home page
If you want a link to the blog page as well use
wp_page_menu().