Load child template based on parent

I have child page templates that need to be automatically applied based on the parent template.

I’m wondering if there is anyway WordPress handles this.

Read More

This is the solution I came up with. (in page.php)

<?php 
//Check parent template 
if ($post->post_parent != $post->ID )
{
    //Get parent template filename
    $parentTemplate = get_post_meta($post->post_parent,'_wp_page_template',true);
}

switch ($parentTemplate) {
    case 'about.php':
        get_template_part( 'child_templates/content', 'about-child' );
        break;
    default:
        get_template_part( 'content', 'page' );
}
?>

Edit

Function to apply parent template to child pages.

function switch_page_template() {
    global $post;
    // Checks if current post type is a page, rather than a post
    if (is_page()){
        $ancestors = $post->ancestors;

        if ($ancestors) {
            $parent_page_template = get_post_meta(end($ancestors),'_wp_page_template',true);
            $template = TEMPLATEPATH . "/{$parent_page_template}";
            if (file_exists($template)) {
            load_template($template);
            exit;
        }
        } else {
            return true;
        }
    }
}

add_action('template_redirect','switch_page_template');

Check if page is parent or child

function is_subpage() {
    global $post;                              // load details about this page

    if ( is_page() && $post->post_parent ) {   // test to see if the page has a parent
        return true;             // return the ID of the parent post

    } else {                                   // there is no parent so ...
        return false;                          // ... the answer to the question is false
    }
}

The template looks like this now

<?php
/*
Template Name: About Us
*/
?>

<?php get_header(); ?>

<?php if (is_subpage()): ?>
    <?php get_template_part( 'templates/content', 'about-child' ); ?>
    <?php else: ?>
    <?php get_template_part( 'templates/content', 'about-parent' ); ?>
<?php endif ?>

<?php get_footer(); ?>

Related posts

2 comments

  1. Instead of putting something on the template, you can keep templates clean and add to functions.php a function that use 'template_include' action hook to check parent page template and return same template for children pages.

    add_action('template_include', 'auto_child_template');
    
    function auto_child_template( $template = '' ) {
      if ( ! is_page() ) {
        return $template;
      } else {
        $page = get_queried_object();
        $ancestors = get_post_ancestors( $post );
        $templates = array();
        // add ancestors page templates to $templates array
        foreach ( $ancestors as $ancestor ) {
          $templates[] = get_page_template_slug( $ancestor );
        }
        // remove empty values
        $templates = array_filter($templates);
        // if no ancestors has a template return current one
        if ( empty($templates) ) return $template;
        // fallback
        $templates[] = 'page.php';
        return locate_template( $templates, FALSE );
      }
    }
    
  2. That looks pretty good. Sounds like something Drupal would be good at.

    WordPress has a wrapper function for the get_post_meta() you’re using: get_page_template_slug()

    Another way you might approach this is to have a function in the functions file that changes the child template on save if the parent has a particular template. In that way if you ever wanted to move that page it would carry the same page template without needing to have a parent under it that has a particular template.

    EDIT

    Changing things on post save requires you to add an action to save_post

    function my_change_page_template( $post_id ) {
    
        // If this is just a revision, don't do anything
        if ( wp_is_post_revision( $post_id ) )
            return;
        if ($post->post_parent != $post->ID ) {
            $parentTemplate = get_post_meta($post->post_parent,'_wp_page_template',true);
        }
        $template = '';
        switch ($parentTemplate) {
            case 'about.php':
                $template = 'about-child.php';
            break;
        }
        if(!empty($template)) {
            update_post_meta( $post_id, '_wp_page_template', $template );
        }
    }
    add_action( 'save_post', 'my_change_page_template' );
    

    I haven’t tested this, but it should be pretty close to what you want. In this way you’ll be testing to parent template and setting the child template based on what gets returned. This will be fired on save post, but not on revisions.

    Let me know if this doesn’t make sense.

Comments are closed.