theme_(post_type)_templatesfilter-hookWP 3.9.0

Allows you to add or remove page templates for post types. These templates can be selected when publishing a post in the admin area.

Page templates are created with comments in the template file:

/*
 * Template Name: My Page Template
 * Template Post Type: post, page, product
 */

The filter can:

  • Specify a file path and template name when WordPress cannot discover the file automatically or when it is located in a plugin.
  • Remove a template file from the selection list, for example when the template exists in the theme but should be disabled.

The dynamic $post_type part of the hook name specifies the post type. Possible hook names include:

Usage

add_filter( 'theme_(post_type)_templates', 'wp_kama_theme_post_type_templates_filter', 10, 4 );

/**
 * Function for `theme_(post_type)_templates` filter-hook.
 * 
 * @param string[]     $post_templates Array of template header names keyed by the template file name.
 * @param WP_Theme     $theme          The theme object.
 * @param WP_Post|null $post           The post being edited, provided for context, or null.
 * @param string       $post_type      Post type to get the templates for.
 *
 * @return string[]
 */
function wp_kama_theme_post_type_templates_filter( $post_templates, $theme, $post, $post_type ){

	// filter...
	return $post_templates;
}
$post_templates(string[])
Array of templates as key => value pairs. The key is the template file path relative to the theme directory, and the value is the template name displayed in the admin area.
$theme(WP_Theme)
Theme WP_Theme object.
$post(WP_Post|null)
WP_Post object for the post whose template list is being displayed.
$post_type(string)
Post type whose template list is being displayed.

Examples

#1 Add a page template

Suppose the theme contains tpl/page/exchanges.php. Because the file is in tpl/page/, WordPress does not recognize it as a template file: WordPress searches the theme root and one directory level below it. The file can be added to the template list for creating and editing posts as follows:

// Add a page template.
add_filter( 'theme_page_templates', 'add_theme_page_templates' );

function add_theme_page_templates( $templates ){

	$templates['tpl/page/exchanges.php'] = 'Exchange Template Page';

	return $templates;
}

The list then contains:

#2 Remove an existing page template from the list

Suppose the theme provides templates that will not be used. Remove them from the list:

// Remove existing page templates from the list.
add_filter( 'theme_page_templates', 'remove_theme_page_templates' );
add_filter( 'theme_post_templates', 'remove_theme_page_templates' );

function remove_theme_page_templates( $templates ) {

	unset( $templates['template-full-width-cover.php'] );
	unset( $templates['template-full-width.php'] );

	// A file in a subdirectory.
	unset( $templates['template/only-content.php'] );

	return $templates;
}

#3 Filter page templates by blog ID

Suppose there is a Food blog with ID 2 and a page-food.php template that should be used only for that blog. This example removes the page template from other blogs' dropdowns:

add_filter( 'theme_page_templates', 'wpdocs_filter_theme_page_templates', 20, 3 );

/**
 * Filter the theme page templates.
 *
 * @param array    $page_templates Page templates.
 * @param WP_Theme $this           WP_Theme instance.
 * @param WP_Post  $post           The post being edited, provided for context, or null.
 * @return array (Maybe) modified page templates array.
 */
function wpdocs_filter_theme_page_templates( $page_templates, $this, $post ) {

	$current_blog_id = get_current_blog_id();
	$food_blog_id    = 2;

	if ( $current_blog_id != $food_blog_id ) {

		unset( $page_templates['page-food.php'] );
	}

	return $page_templates;
}

#4 Add a theme template file from a plugin

See How to create a page template from a plugin.

Changelog

Since 3.9.0 Introduced.
Since 4.4.0 Converted to allow complete control over the $page_templates array.
Since 4.7.0 Added the $post_type parameter.

Where the hook is called

WP_Theme::get_page_templates()
theme_(post_type)_templates
wp-includes/class-wp-theme.php 1451
$post_templates = (array) apply_filters( "theme_{$post_type}_templates", $post_templates, $this, $post, $post_type );

Where the hook is used in WordPress

wp-includes/default-filters.php 680
add_filter( 'theme_wp_navigation_templates', '__return_empty_array' );