1

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.

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(); ?>
2

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 );
  }
}
  • I like this approach since I'm using Advanced Custom Fields and I can apply fields based on template instead of specific pages, but the child pages use a different layout, so in my template.php I will check if parent or child page and load template part based on that? – hyperdrive Jan 23 '14 at 20:43
  • @hyperdrive I've updated the function to take into accounts page templates of all ancestors: a child page will take the parent template (if any) or the grandparent template (if any) or the grang-grandparent template (if any) and so on. After that you can use the template you have in your question after edit. The only think I will not use there is is_subpage function: it really don't save much to type, but has a (very little indeed) impact on performance that can be avoided simply using if ( $post->post_parent ) where you have if ( is_subpage() ). – gmazzap Jan 23 '14 at 21:59
0

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.

  • I like the idea of saving the template on save but I don't know how to go about doing that. That way I could add meta fields in the backend based on is child and page template. – hyperdrive Jan 23 '14 at 21:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.