Post Type Templates in 4.7

WordPress has supported custom page templates for over 12 years, allowing developers to create various layouts for specific pages. While this feature is very helpful, it has always been limited to the ‘page’ post type and not was not available to other post types. With WordPress 4.7, it will be.

By opening up the page template functionality to all post types, the template hierarchy’s flexibility continues to improve.

In addition to the Template Name file header, the post types supported by a template can be specified using Template Post Type: post, foo, bar. Here’s an example:

<?php
/*
Template Name: Full-width layout
Template Post Type: post, page, product
*/

// … your code here

That way, you’ll be able to select this full-width template for posts, pages, and products.

When at least one template exists for a post type, the ‘Post Attributes’ meta box will be displayed in the back end, without the need to add post type support for 'page-attributes' or anything else. The ‘Post Attributes’ label can be customized per post type using the 'attributes' label when registering a post type.

Backward Compatibility

Let’s say you want to publicly release a theme with support for post type templates. WordPress versions before 4.7 will ignore the Template Post Type header and show the template in the list of page templates, even though it only works for regular posts. To prevent that, you can hook into the theme_page_templates filter to exclude it from the list. Here’s an example:

/**
 * Hides the custom post template for pages on WordPress 4.6 and older
 *
 * @param array $post_templates Array of page templates. Keys are filenames, values are translated names.
 * @return array Filtered array of page templates.
 */
function makewp_exclude_page_templates( $post_templates ) {
	if ( version_compare( $GLOBALS['wp_version'], '4.7', '<' ) ) {
		unset( $post_templates['templates/my-full-width-post-template.php'] );
	}

	return $post_templates;
}

add_filter( 'theme_page_templates', 'makewp_exclude_page_templates' );

That way you can support custom post type templates in WordPress 4.7 and beyond while maintaining full backward compatibility.

Note that theme_page_templates is actually a dynamic theme_{$post_type}_templates filter. The dynamic portion of the hook name, $post_type, refers to the post type supported by the templates. E.g. you can hook into theme_product_templates to filter the list of templates for the product post type.

For further information about this new feature, see the corresponding ticket #18375.