Since WP2.9 WordPress has had the ability to declare custom post types. However, up until now you have had to build your own backend UI to manage those posts. Now in the up coming 3.0 version WordPress can provide that too almost automatically, theres a great tutorial at wpengineer.com http://wpengineer.com/impressions-of-custom-post-type/ that shows you how to add a custom post type and what options are available.
Anyway today I set about exploring 3.0 alpha 1 and had a mess with custom posts, and immediately decided it would have saved days of work when building this site alone, but what I couldn’t figure out was how to customise the display of my custom posts, after a few searches I came across someone in the WP.org forums with the same problem and no answers.
So I did some digging in the 3.0 code to figure out what template was getting used, and how it was getting chosen. After an hour or so looking at the WP_Query class, and the theme.php file in the core I came up with a simple and more advanced solution.
Simple Solution
Its build in, just not documented, atleast anywhere I could find. The template used for a custom post view is decided by the ‘get_single_template()’ function in the wp-includes/theme.php file. And it basically tells locate_template() to look for single-’post_type’.php or single.php.
So the simplest way to customise the way a custom post is displayed is to add a template file to your theme with the name single-xxxxxx.php
Advanced Solution
Anyway that solution worked but what if you want to do other stuff like single out a specific custom post by id, or anything.
Well a bit more reverse engineering and I came up with a solution. First I wrote a simple is_ funtion for my custom post type ‘publication’, that way I could test for them.
function is_publication()
{
$post_type = get_query_var('post_type');
// short had for if / else;
return $post_type == 'publication' ? true : false;
}
Then I added my own get_xxx_template function to choose which template file to load including publication-id.php and fallback to single.php if none is found.
function get_publication_template()
{
global $wp_query;
$object = $wp_query->get_queried_object();
$templates = array( 'publication-'. $object->ID .'.php',
'publication.php',
'single-'. $object->post_type .'.php',
'single.php' );
$page_template = get_post_meta( $object->ID , '_wp_page_template', true );
if ( !empty( $page_template ) ) {
$templates = array( $page_template ) + $templates;
}
return locate_template( $templates );
}
Finally I added a function to use the ’template_inlcude’ filter hook. It uses is_publication to check if the publication templates need to be loaded, and if so replaces/filters the template being loaded with the template determined by my get_publication_template function.
function set_publication_template( $template )
{
if ( is_publication() ) {
$template = get_publication_template();
}
return $template;
}
add_filter('template_include', 'set_publication_template');
And Finally the code in full including declaration.
function ttd_post_type_publication()
{
register_post_type( 'publication',
array( 'label' => __('Publications'),
'public' => true,
'show_ui' => true,
'supports'=> array(
'post-thumbnails',
'excerpts',
'custom-fields',
'comments' ) ) );
register_taxonomy_for_object_type('post_tag', 'publication');
}
function is_publication()
{
$post_type = get_query_var('post_type');
// short had for if / else;
return $post_type == 'publication' ? true : false;
}
function get_publication_template()
{
global $wp_query;
$object = $wp_query->get_queried_object();
$templates = array( 'publication-'. $object->ID .'.php',
'publication.php',
'single-'. $object->post_type .'.php',
'single.php' );
$page_template = get_post_meta( $object->ID , '_wp_page_template', true );
if ( !empty( $page_template ) ) {
$templates = array( $page_template ) + $templates;
}
return locate_template( $templates );
}
function set_publication_template( $template )
{
if ( is_publication() ) {
$template = get_publication_template();
}
return $template;
}
add_filter('template_include', 'set_publication_template');
add_action('init', 'ttd_post_type_publication');

