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.