1

After taking a look through the questions suggested to possibly have my answer, I still can not seem to find something that I references the post-template php files.

I have two custom post types that I am attempting to combine into a single post-type. I will call the custom post types 'Client' and 'Project'. What I have done is create a 'Clients & Projects' custom post type, and set each one of the 'Clients' to parent and the subsequent 'Projects' to Children within the 'Clients & Projects'.

I have PHP templates created already, and they work fine for each of the post types individually, but I can't figure out how to set one of the templates to load for the 'Clients' (parent-posts) and the other template to load for the 'Projects' (child-posts).

The naming of the files is as follows:

  • Clients would be clients_projects_parent.php
  • Projects would be clients_projects_child.php

I found this code snippet here, but it did not solve my problem.

function switch_page_template() {
    global $post;
    // Checks if current post type is a page, rather than a post
    if (is_page()){
        // Checks if page is parent, if yes, return
        if ($post->post_parent == 0)
            return true;
        else if ($post->post_parent != $post->ID){
            $parent_page_template = get_post_meta($post->post_parent,'_wp_page_template',true);
            $template = TEMPLATEPATH . "/{$parent_page_template}";
            if (file_exists($template)) {
                load_template($template);
                exit;
            }
        }
    }
}

add_action('template_redirect','switch_page_template');

My ultimate hope would be for each of the Parent and Child posts to load a different PHP template respectively.

Update:

I was tinkering around and tried this:

add_action('template_redirect', 'get_template');

function get_template(){
    global $wp;
    global $wp_query;

    if(is_page('client_project') || '0' === $post->post_parent){
        include(TEMPLATEPATH . '/single-client_project.php');
    }elseif(is_page('client_project') || $post->post_parent > 0){
        include(TEMPLATEPATH . '/single-client_project_child.php');
    }
    else{
        include(TEMPLATEPATH . '/single-client_project.php');
    }
}

I placed a conditional statement in the templates that I am trying to call/redirect as well that looks like this:

global $post;

if ( is_page('client_project') || '0' == $post->post_parent ) {
    echo "<h1>This is a parent page</h1>";
    echo "<p>post parent = " . $post->post_parent . "</p>";

} else {
    echo "<h1>This is a child page</h1>";
    echo "<p>post parent = " . $post->post_parent . "</p>";
}

Now, what is happening is when the posts load each one gives the correct indication from the echo loop that was placed in the template files ie. parent post prints 'This is a parent page' and gives the correct post parent number '0', but the templates are still loading wrong (ether the parent or the child template loads not each one for each type)...

I only tried this after seemingly every other method failed me. I am sure that I am missing something, but I really can't figure it out.

FINAL UPDATE:

I finally got the templates to swap out. Although it is in what I can only imagine is the worst possible way. I basically went into the 'parent' template and placed an if statement just before the code of the page. It looks like this:

<?php 
    global $post;

    if(is_page('client_project') || $post->post_parent > 0){
        include(TEMPLATEPATH . '/single-client_project-child.php');
    }
?> 

I read after I got this to work that TEMPLATEPATH was depreciated, so I will most likely swap that out, but I am going to call this answered, @G. M. if you wanted to, I would really appreciate you writing the correct way to do this, or at the very least a better way. I invite everyone who comes across this question to do the same. Cheeers!

2
  • Is it only me who could not understand exactly what were you trying to explain and what do you want to do.
    – Robert hue
    Nov 22, 2014 at 3:27
  • 'My ultimate hope would be for each of the Parent and Child posts to load a different PHP template respectively'... How should I accomplish my hope? Nov 24, 2014 at 19:18

1 Answer 1

1

Simplest way is to use single_template filter hook (one of the {$type}_template hooks).

It is fired by WordPress to filter the template file found for singular post requests.

add_filter('single_template', function($template) {

  $queried = get_queried_object();

  if ( $queried->post_type === 'clients_projects' ) { // only for this CPT
    // file name per OP requirements
    $file = 'clients_projects_';
    $file .= $queried->post_parent ? 'child' : 'parent';

    // using `locate_teplate` to be child theme friendly
    return locate_template("{$file}.php") ? : $template;
  }

  return $template;

});

How it works

When you visit an url on a WordPress site, WordPress translate that url into a set of query arguments, and trigger a database query using them.

There are different types of query, for a page, for an archive, for a post, and so on. Look at Conditional Tags page on Codex, there is an exhaustive description of all the query types.

In your case you need to target single query type, because you want to change the template used whn a single CPT is required.

After a query is triggered, WordPress looks into theme folder to find a template to use to display query results. Look at template hierarchy to understand which file is used to each type of query.

When a file is found, before actually include that file, WordPress filter it using 2 filters.

In code above, I used the 'single_template' filter to change the template WordPress will load, returning a different template from a callback attacched to that filter.

However, that filter is triggered for every single request, even for standard posts and other CPTs, so before change the template I checked if current queried post is one of the CPT we want target. To obtain the current queried post I used [get_queried_object()][6] that in singular requests returns the post object.

If current post is not of target post type, I just return the file WordPress found, without altering it.

If current post is one of target post type, I build the template name looking at the post_parent attribute of the post: if the post has a parent I build 'clients_projects_child.php' if the post has not a parent I return 'clients_projects_parent.php'.

Before actually returning the template file, I use locate_template to see if in theme (or in child theme) that template file exists or not. If it exists I return it, in this way WordPress instead of loading the default template load the custom template, if the template doesn't exists I return the default template, that is the one WordPress found.

1
  • This definitely looks like it is going to work, and forgive my novice question, but how does it work? I am completely lost. I placed it in the functions.php of my theme folder. I played around with it a bit (meaning that I changed values to see what was being effected), but I can't get it to change the template loading the same file each time. I am sure I am missing some piece of the 'puzzle'. Thanks for your answer, I am sure that it is the right one. Nov 24, 2014 at 19:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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