The Problem
Recently, I worked on a Web site for a client that had already been developed by another agency. My task was add some extra functionality that was too complex for the original developer to implement. After taking a look at the code, I quickly understood why: the person who created their theme and setup the site was obviously a designer, not a developer.
Among some of the mistakes that were made was an over-use of plug-ins instead of taking advantage of built-in WordPress functionality. After completing my part of the project, I decided to run through the site and see what I could do to make it more efficient. While doing so, I discovered that a plug-in was being used to redirect all parent pages back to the home page. These parent pages contained no content and their only purpose was for organization. I do not normally recommend using pages for this purpose, but this is how the client wanted their site setup. I pointed out to the client that they were missing out on a great opportunity to keep their visitors engaged instead of causing them to be confused. My solution to this issue was to “point” those parent pages to a child of the clients choosing.
The Solution

The first step to solving this problem involved going through each page (all 20 of them) and changing the Order parameter, found in Page Attributes next to the page editor, to match the arrangement of the previously configured navigation menu, starting at 0 (see Figure 1). I could have created a new meta field for this, but I figured that using an existing field was better as it would save time and money. After that task was completed, I got down to the fun part, the real “meat and potatoes”: writing the code to do the redirection. This is what I came up with:
function my_template_redirect() {
global $post;
if ( ! is_object( $post ) )
return;
// Redirect all parent pages to their first child (determined by the order
// set in Page Attributes) if one exists
if ( 'page' == $post->post_type && 0 == $post->post_parent ) {
$child = get_children( array(
'numberposts' => 1,
'post_parent' => $post->ID,
'post_type' => 'page',
'post_status' => 'publish',
'orderby' => 'menu_order',
'order' => 'ASC'
) );
if ( 1 == count( $child ) ) {
wp_redirect( get_permalink( current( $child )->ID ), 301 );
exit;
}
}
}
add_action( 'template_redirect', 'my_template_redirect', 0 );
Explanation
This solution uses the WordPress action hook template_redirect, which is executed before WordPress determines which template to use to display the requested page. First, the callback gets the $post¹ variable and verifies that it is an object. If it is not an object, then the action is terminated. Next, the post is checked to make that it is a root level page, like so:
if ( 'page' == $post->post_type && 0 == $post->post_parent ) {
If it is, the get_children() function is used to grab the first child page with an order of 0. This portion of code can also be modified to get the first child by id, date, or whatever other parameter is required, as shown in the following example:
$child = get_children( array( 'numberposts' => 1, 'post_parent' => $post->ID, 'post_type' => 'page', 'post_status' => 'publish', 'orderby' => 'post_date', 'order' => 'DESC' ) );
After making sure that a child page was returned, its URL is retrieved by passing its id to the get_permalink() function. Last, the wp_redirect() function is used to take the visitor to that address. Note that this a permanent redirect and not temporary one, so “301″ is passed as the second parameter instead of the default “302″. Additionally, after using wp_redirect(), exit() must be called to end the script and make sure that no other code is executed.
Conclusion
Although this solution worked out great for my particular situation, your mileage may vary based on the requirements of your project. Changes may need to be made to the code before it will do what you need it to. You may use the provided code for whatever legal purpose you see fit provided that you include proper attribution along side a link back to this post.
Example of proper attribution:
/** * The following code was found at http://josephleedy.me/blog/wordpress-redirect-parent-page-to-child * and is Copyright (c) 2013 Joseph Leedy. Used with permission. */
Feel to ask me any questions or provide me with any comments and suggestions that you have by using the comment form below but please keep them on topic. Any message that contains questions that are not related to this post or multiple suspicious links will be deleted.
References
- ¹ An example of the
$postobject’s properties can be found on the Codex page for theget_post()function. - WordPress template action hooks



