Custom template for custom post type single post wordpress

Posted on January 22, 2017 in Web Dev

I recently had a somewhat unique situation whereby I needed a custom template per post of a custom post type.

Consider the custom post type being ‘services’, then you’d set it like this:

$labels = array(
 'name' => 'Services',
 'singular_name' => 'Service',
 'menu_name' => 'Services',
 'parent_item_colon' => 'Parent Service',
 'all_items' => 'All Services',
 'view_item' => 'View Service',
 'add_new_item' => 'Add New Service',
 'add_new' => 'Add New',
 'edit_item' => 'Edit Service',
 'update_item' => 'Update Service',
 'search_items' => 'Search Service',
 'not_found' => 'Not Found',
 'not_found_in_trash' => 'Not found in Trash',
 );
 $args = array(
 'label' => 'Services',
 'description' => 'Service',
 'labels' => $labels,
 'hierarchical' => true,
 'public' => true,
 'show_ui' => true,
 'show_in_menu' => true,
 'show_in_nav_menus' => true,
 'show_in_admin_bar' => true,
 'menu_position' => 5,
 'can_export' => true,
 'has_archive' => true,
 'exclude_from_search' => false,
 'publicly_queryable' => true,
 'supports' => array( 'thumbnail', 'editor', 'title', 'excerpt', 'page-attributes' )
 );
 // Registering your Custom Post Type
 register_post_type( 'Services', $args );

The URL structure follows something like:

/services/web-development

/services/consulting

/services/cooking

…and so on.

In this example, I was looking to have a drastically different template for each of these custom post type pages.

The custom archive template for this is pretty simple, just create a file called ‘archive-services.php’. Similarly, the single post type template is simple, just create a file called ‘single-services.php’.

Creating a post-specific template

The difficulty is where you need a specific template for each post, based on ID or slug.

Usually you can do this for pages or posts by creating a file called ‘page-{slug}.php’ or ‘page-{ID}.php’ (in the case of the post being a page post type.

To do the same thing for a custom post type is a little bit more complicated. In an ideal world you could simply create ‘single-{$posttype}-{$slug}.php’ – but alas this does not work. You need to create your own filter which bypasses the tempalte selection, based on the post_type name.

In your functions.php file use the following:

<p class="lang-php prettyprint prettyprinted" style="color: #393318;"><code><span class="pun" style="color: #303336;">add_filter( 'single_template', function( $template ) {
global $post;
$post_type_name = 'services';
if ( $post->post_type === $post_type_name ) {
$locate_template = locate_template( "single-".$post_type_name."-{$post->post_name}.php" );
if ( ! empty( $locate_template ) ) {
$template = $locate_template;
}
}
return $template;
} );

Don’t forget to replace ‘services’ with the name of your own post_type!

Using this method, you’ll now be able to create a unique template for each of your custom post type posts.

Further reading: https://developer.wordpress.org/themes/basics/template-hierarchy/

Leave a comment

Was this helpful? Did I miss something? Do you have a question? Get in touch, or tell me below.