When the child_of
parameter is set, get_pages()
will use get_page_children()
to get the child pages, and unfortunately, the sort_column
will no longer be used, hence the final list will not be sorted by the specified custom sort column, so you’ll need to use your own code for getting the list with the expected sort column (and order).
Here’s an example which uses a custom function that’s called recursively (until all child pages are retrieved) and then walk_page_tree()
is used (instead of wp_list_pages()
which has the same issue as get_pages()
) to output the pages in a list (li
) layout:
// In the theme functions file:
function my_get_pages( $parent, $orderby = 'menu_order', $order="ASC" ) {
$pages = get_pages( array(
'parent' => $parent,
'sort_column' => $orderby,
'sort_order' => $order,
) );
$children = array();
foreach ( $pages as $page ) {
$children[] = $page;
// Retrieve grandchildren.
$children2 = my_get_pages( $page->ID, $orderby, $order );
if ( ! empty( $children2 ) ) {
$children = array_merge( $children, $children2 );
}
}
return $children;
}
// In your template:
$parent = 123; // parent post/Page ID
$pages = my_get_pages( $parent );
echo '<ul>' .
walk_page_tree( $pages, 0, get_queried_object_id(), array() ) .
'</ul>';
Here’s another example, similar to the above, but this one doesn’t use walk_page_tree()
— and you’ve got full control over the HTML:
// In the theme functions file:
function my_wp_list_pages( $parent, $orderby = 'menu_order', $order="ASC" ) {
$pages = get_pages( array(
'parent' => $parent,
'sort_column' => $orderby,
'sort_order' => $order,
) );
if ( empty( $pages ) ) {
return;
}
// Just change the HTML markup based on your liking..
echo '<ul>';
foreach ( $pages as $page ) {
printf( '<li><a href="%s">%s</a></li>',
esc_url( get_permalink( $page ) ),
get_the_title( $page ) );
// Display grandchildren.
my_wp_list_pages( $page->ID, $orderby, $order );
}
echo '</ul>';
}
// In your template:
$parent = 123; // parent post/Page ID
my_wp_list_pages( $parent );