0

I am creating a plugin that registers a custom post type, and I want it to be displayed using the theme's page.php template, rather than the post.php. I set the hierarchical flag when I register it, but the post.php template is still called.

Way, way down inside wp-includes/post.php, where it appears to decide which template to use, is the code:

if ( ! empty( $postarr['page_template'] ) && 'page' == $data['post_type'] ) {
    $post->page_template = $postarr['page_template'];
    $page_templates = wp_get_theme()->get_page_templates( $post );
    ...

which makes me think that the post template is used unless post_type is exactly 'page'.

I don't want to define a template of my own, because I want to work with any theme. I just want to tell WordPress which of the current theme's templates to use.

There's an action hook, called get_template_part_{$slug} that might do the trick, but I'm not sure what it expects, and the documentation for that one is unusually spotty.

1
  • And no sooner do I post that than I find the 'single_template' filter hook. Now if I can figure out how to return the page template for the current theme, I'm on my way.
    – Jerry
    May 5, 2016 at 1:06

2 Answers 2

1

You can filter template_include and then let WordPress search for a page template in all valid templates like page.php, index.php and even files from a parent theme.

add_filter( 'template_include', function( $template ) {
    return is_singular( [ 'YOUR_POST_TYPE' ] ) ? get_page_template() : $template;
});
2
  • Thanks! This looks really good. I'm just waiting for a free moment to try it out.
    – Jerry
    May 9, 2016 at 1:46
  • One of the themes I work with uses get_template_part() to load the template for that part of the page; when I call get_page_template() in that context I don't get anything back. I've got a hack in place to filter request, which then causes my type to return true for is_page(), but it makes me a little nervous.
    – Jerry
    Jun 5, 2016 at 1:00
0

That's exactly it. You should be able to use something like this, replacing the your_post_type:

function get_custom_post_type_template($single_template) {
    global $post;

    if ($post->post_type == 'your_post_type') {
        $single_template = get_stylesheet_directory_uri() . '/page.php';
    }
    return $single_template;
}
add_filter( 'single_template', 'get_custom_post_type_template' );
5
  • That was all well and good and I was excited until I noticed that the other theme I'm testing on doesn't have a page.php, but instead uses content-page.php, presumably called by get_template_part somewhere (maybe the default page.php?). So I can't count on page.php being in the theme directory. Is there a way to ask Wordpress "if you were to render a page right now, what template would you use?"
    – Jerry
    May 5, 2016 at 1:34
  • There's no way that your other theme can only be using content-page.php. It must be using page.php, which then includes content-page.php.
    – frogg3862
    May 5, 2016 at 1:37
  • Curious. There is no page.php file in the theme's directory, and no template listed in the styles.css header, which I take to mean it's not a child theme that uses another theme's page.php. Indeed, all the other themes have a page.php file. I assume there's some global Wordpress fallback, but I can't find it.
    – Jerry
    May 5, 2016 at 2:13
  • According to the template hierarchy, if page.php doesn't exist, then it may use singular.php or index.php developer.wordpress.org/files/2014/10/template-hierarchy.png
    – frogg3862
    May 5, 2016 at 2:23
  • Turns out it has custom loop in its index.php that calls a function that renders the stuff. Yarg. So... back to figuring out how to make is_singular() be false and is_page() be true, I guess.
    – Jerry
    May 5, 2016 at 2:36

Your Answer

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

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