由于wp_list_pages()
杠杆作用get_pages()
要实际检索页面帖子get_pages()
实现独立于WP_Query
\'s、 无法使用不受直接支持的任意查询变量get_pages()
, 包括…在内year
, mothnum
, day
, date_query
, 等
为了继续使用wp_list_pages()
为此,我认为最优雅的解决方案是实现自定义Walker_Page
class 你可以传给wp_list_pages()
作为参数,以自定义生成的HTML。
作为一个附加好处,此解决方案继续使用get_pages()
查询而不是每年一次查询,并且可以流畅地处理孙子页面,并随着年份的增加而继续扩展。
量身定制的Walker_Page
在WordPress中
"Walkers" 类的设计目的是获取表示分层或树状数据的列表,如类似分层帖子类型、分类法或导航菜单项的列表,并将其转换为标记以供显示。
wp_list_pages()
提供一个参数以将自定义Walker传递给它,以代替the Walker_Page
class 它默认使用,允许您自定义函数生成的标记。
// mytheme/lib/class-year-accordion-walker-page.php
// (or functions.php, or some other theme library code location)
/**
* A Walker_Page customized to additionally group first-level pages into lists based
* on their publication year.
**/
class Year_Accordion_Walker_Page extends Walker_Page {
/**
* Creates the opening markup for a year\'s accordion group.
*
* @param string &$output The string to append output to.
* @param int $year The year which to build group markup for.
* @param boolean $is_active If this year matches the publication date for the current page, as indicated by "child_of".
* @param array $args Any additional arguments passed to `walk()`.
**/
public function start_accordion_group( &$output, $year, $is_active = false, $args = [] ) {
// Setup HTML classes to be added to various parts of the markup.
$container_classes = [];
$header_classes = [ \'ui-accordion-header\' ];
$content_classes = [ \'ui-accordion-content\' ];
if( $is_active ) {
$container_classes[] = \'current_page_ancestor\';
$header_classes[] = \'ui-accordion-header-active\';
$content_classes[] = \'ui-accordion-content-active\';
}
// Add this accordion group\'s opening markup to the output, joining each line with the configured indentation.
$output .= implode(
"\\n\\t",
[
\'<li class="\' . implode( \' \', $container_classes ) . \'">\',
\'<h3 class="\' . implode( \' \', $header_classes ) . \'">\' . $year . \'</h3>\',
\'<ul class="\' . implode( \' \', $content_classes ) . \'">\',
]
);
}
/**
* Creates the closing markup for a year\'s accordion group.
*
* @param string &$output The string to append output to.
* @param int $year The year which to build group markup for.
* @param boolean $is_active If this year matches the publication date for the current page, as indicated by "child_of".
* @param array $args Any additional arguments passed to `walk()`.
**/
public function end_accordion_group( &$output, $year, $is_active = false, $args = [] ) {
$output .= implode(
"\\n",
[
"\\t</ul>", // Close the accordion group\'s page list.
\'</li>\', // Close the accordion group\'s container li.
]
);
}
/**
* Display array of Pages, grouped by the topmost pages\' publication year.
*
* $max_depth = 0 means display all levels.
* $max_depth > 0 specifies the number of display levels.
*
* @param array $pages An array of WP_Post items.
* @param int $max_depth The maximum hierarchical depth.
* @param mixed ...$args Optional additional arguments.
* @return string Markup representing $pages grouped by publication year.
**/
public function walk( $pages, $max_depth = 0, ...$args ) {
$output = \'\';
// Invalid parameter or nothing to walk.
if ( $max_depth < 0 || empty( $pages ) )
return $output;
$options = $args[0]; // When used with `walk_page_tree()` this is an assoc array of any additional arguments.
$current_page_id = $args[1]; // When used with `walk_page_tree()` this is the current post ID.
$active_page_year = null; // Keep track of which year the current_page_id Page was published in for custom classes, etc.
$parent_field = $this->db_fields[\'parent\']; // Inherited from `Walker_Page` - will always be `ID`.
$parent_id = isset( $options[\'child_of\'] ) ? $options[\'child_of\'] : 0; // The ID of the top-level common parent, if any.
$top_level_pages_by_year = []; // A mapping of year => top-level pages (parent is $parent_id, or no parent if $parent_id is not set).
$child_pages_by_parent = []; // A mapping of parent_id => pages, collecting all pages whose parent is not $parent_id (or who have a parent, if $parent_id is not set)
// Split $pages into $child_pages_by_parent and $top_level_pages_by_year.
foreach( $pages as $page ) {
$year = date( \'Y\', strtotime( $page->post_date ) );
if( $page->ID === $current_page_id )
$active_page_year = $year; // If this is the current page, record the year in which it was published.
// If this is a grandchild page, we don\'t care about it\'s publish date - just add it to the map of parent_id => child pages.
if( ( empty( $parent_id ) && ! empty( $page->$parent_field ) ) || ( ! empty( $parent_id ) && $page->$parent_field !== $parent_id ) ) {
if( ! isset( $child_pages_by_parent[ $page->$parent_field ] ) )
$child_pages_by_parent[ $page->$parent_field ] = [];
$child_pages_by_parent[ $page->$parent_field ][] = $page;
continue;
}
if( ! isset( $top_level_pages_by_year[ $year ] ) )
$top_level_pages_by_year[ $year ] = [];
$top_level_pages_by_year[ $year ][] = $page; // Add the top level page to it\'s respective year list.
}
// Build the markup, one year at a time.
foreach( $top_level_pages_by_year as $year => $pages ) {
// Build the opening markup for this year\'s accordion group.
$this->start_accordion_group( $output, $year, $year == $active_page_year, $args );
// Add each top-level page in the group\'s child tree markup as per usual.
foreach( $pages as $page )
$this->display_element( $page, $child_pages_by_parent, $max_depth, 1, $args, $output );
// Close this year\'s accordion group.
$this->end_accordion_group( $output, $year, $year == $active_page_year, $args );
}
return $output;
}
}
有了上述课程,
wp_list_pages()
可以调用以将其用作:
// Template file
wp_list_pages(
[
\'title_li\' => \'&\',
\'child_of\' => $id,
\'show_date\' => \'modified\',
\'date_format\' => $date_format,
\'walker\' => new Year_Accordion_Walker_Page,
]
);
收尾工作
对于蛋糕上的糖霜,您甚至可以创建一个;模板标签;函数在必要时加载和利用此类:
// functions.php
// (or other library file loaded by functions.php)
/**
* Display pages in an accordion, grouped by year. Loads the customized
* Walker_Page if it\'s not already available.
*
* @param array $args Array of wp_list_pages() arguments.
**/
function wpse390524_page_year_accordion( $args = [] ) {
if( ! class_exists( \'Year_Accordion_Walker_Page\' ) )
require_once get_stylesheet_directory() . \'/lib/class-year-accordion-walker-page.php\';
$args[\'walker\'] = new Year_Accordion_Walker_Page;
wp_list_pages( $args );
}
// Template file
wpse390524_page_year_accordion(
[
\'title_li\' => \'&\',
\'child_of\' => $id,
\'show_date\' => \'modified\',
\'date_format\' => $date_format,
]
);