Add “virtual” page templates in WordPress - Cobbled Code

A super nifty feature was added to WordPress 4.4: the possibility to dynamically add page templates (#34995).

Previously a theme author would need to add actual custom page template files to their theme. The template would then show up in the Template dropdown of the Page Attributes meta box.

Theme and plugin authors can now add page templates to the Template dropdown by adding a 'name' => 'Title' entry to the list of templates via the theme_page_templates filter.

Add an entry to the page template dropdown

/**
 * Add an entry to the page templates dropdown.
 *
 * This function hooks into the 'theme_page_templates' filter which is
 * documented in wp-includes/class-wp-theme.php.
 *
 * @param array $page_templates  Array of page templates. Keys are filenames,
 *                               values are translated names.
 * @return array Array of page templates including our custom ones.
 */
function prefix_filter_page_templates( $page_templates ) {

	/*
	 * Add an entry to the $page_templates array.
	 * Prefixing the key might be a good idea as
	 * an entry with that key might already exist.
	 */
	$page_templates['prefix_example_template'] = __( 'Example Template', 'textdomain' );

	return $page_templates;
}
add_filter( 'theme_page_templates', 'prefix_filter_page_templates' );

You can find out which template is assigned to a page with the get_page_template_slug( $post ); function.

So what?

A plugin might want to add a page template which adds something to the post content. Perhaps a calendar page template, or a price list page template.

/**
 * Add something to the post content.
 *
 * If the 'prefix_example_template' is selected,
 * add stuff below the post content.
 *
 * @since 1.0.0
 * @param string $content Post content.
 * @return string
 */
function prefix_add_stuff_to_content( $content ) {

	if ( ! is_admin() && is_page() ) {

		$template_slug = get_page_template_slug( $post->ID );

		if ( 'prefix_example_template' === $template_slug ) {
			$content = 'Stuff I want to add goes here' . $content;
		}
	}
	
	return $content;
}
add_filter( 'the_content', 'prefix_add_stuff_to_content' );

Maybe a page with our “Example Template” will not need the text editor in the admin.

/**
 * Remove TinyMCE editor if the 'Example Template' is selected/
 */
function prefix_maybe_remove_editor_support() {

	if ( empty( $_GET['post'] ) ) {
		return;
	}

	$post = get_post( absint( $_GET['post'] ) );

	if ( ! $post ) {
		return;
	}

	$post_type = get_post_type( $_post );

	if ( 'page' !== $post_type ) {
		return;
	}

	if ( 'prefix_example' === get_page_template_slug( $post ) ) {
		remove_post_type_support( 'page', 'editor' );
	}
}
add_action( 'load-post.php', 'prefix_maybe_remove_editor_support' );

Or we might want to add a meta box to the page edit screen if our page template is selected.

/**
 * Add a meta box to the page edit screen if the `prefix_example_template`
 * page template is selected for the page in question.
 */
function prefix_maybe_add_my_cool_meta_box( $post_type, $post ) {
	
	if ( 'page' !== $post_type ) {
		return;
	}

	if ( 'prefix_example_template' !== get_page_template_slug( $post->ID ) ) {
		return;	
	}

	add_meta_box(
		'example-meta-box',
		esc_html__( 'My Cool Meta Box', 'textdomain' ),
		'callback',
		'page',
		'normal',
		'high'
	);
}
add_action( 'add_meta_boxes', 'prefix_maybe_add_my_cool_meta_box', 10, 2 );

Okay, the last two examples are not specifically related to the new “virtual” page templates. I hoped to illustrate some stuff you can do with them.

I’ve been happily using this in my projects (even if frowned upon) to dynamically add page templates for use as archive pages for custom post types. Neat for vanity URLs!

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.