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.

  • 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 '16 at 1:06

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;
  • Thanks! This looks really good. I'm just waiting for a free moment to try it out. – Jerry May 9 '16 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 '16 at 1:00

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' );
  • 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 '16 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 '16 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 '16 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 '16 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 '16 at 2:36

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.