Steve Taylor photo

How to restrict a WordPress page template to one page

WordPress page templates (now applicable to any post type) are designed to be re-used for any number of pages. However, sometimes I want there to be a template that only gets used once. It is possible to tie a template to a specific page by using the page-{slug}.php or page-{id}.php template naming patterns, but slugs and IDs can sometimes be unstable (e.g. across different environments). How to use a template and make sure it only gets used once? As with most cats, there’s probably many ways to skin this one. But here’s one way.

First we need a function to get the ID of the page currently set to the template, if any.

function slt_get_template_page_id( $template ) {
	$page_id = null;

	$pages = get_posts( array(
		'post_type'			=> 'page',
		'posts_per_page'	=> 1,
		'fields'			=> 'ids',
		'meta_key'			=> '_wp_page_template',
		'meta_value'		=> $template
	));

	if ( $pages ) :
		$page_id = $pages[0];
	endif;

	return $page_id;
}

Now we hook into the theme_{$post_type}_templates filter which controls the templates available in the Page attributes drop-down:

add_filter( 'theme_page_templates', 'slt_theme_page_templates', 10, 3 );
function slt_theme_page_templates( $templates, $theme, $post ) {
	$template = 'page_my-template.php';

	$template_page_id = slt_get_template_page_id( $template );
	if ( $template_page_id && ! empty( $post ) && ( $template_page_id != $post->ID ) ) :
		unset( $templates[ $template ] );
	endif;

	return $templates;
}

This checks if there’s already a page set to the template. If there is (and we’re not dealing with that page!), the template is removed from the options.

NB: As is often the case, Quick Edit scuppers things slightly. If necessary, there are ways of disabling Quick Edit completely. Suggestions for making the above theme_page_templates filter work properly for Quick Edit are welcome. The issues seems to be that $post isn’t passed through.

3 comments

  1. Harry E avatar Harry E

    Heya,
    This is exactly what I’ve been looking for, although I’m not sure I’m getting the same result. It’s working to a point, so it won’t let me add more than 1 of a certain template, which is great, but it’s not actually removing the option in the ‘template’ dropdown. If you pick it and publish it’ll revert to the default template. Is that the expected behaviour?
    Thanks so much
    Harry

  2. Steve Taylor avatar Steve Taylor

    It’s a while since I used this and your details aren’t clear, so not sure. I think this’ll only work once the page is created (draft or published). Otherwise $post->ID may not have a value here. You might have to do a bit of debugging – let me know how it goes.

Leave a comment

Your email address will not be published. Required fields are marked *