Custom post types are a new thing in WordPress 3, and they had fallen under my radar until a friend sent me this article on building a video site using WordPress. It sounded like just what I’ve been waiting for, the ability to define new content types with specific fields, one step closer to getting WordPress to behave better as a CMS… until I got to the section about Custom Fields, and realised they’re handled exactly like in Post and Page types, and the only UI fields you can choose from are, guess what, the fields you’ve got for Post and Page. To do anything nice with custom fields, you still need a plugin like Custom Field Template that supports custom post types or have a look at add_meta_box() and get be prepared to get your hands dirty.
What you can do is apply custom taxonomies to your new type. Being able to define taxonomies beyond categories and tags is a relatively new thing as well. But, you guessed right, they behave just like categories and tags, i.e. you can’t force CMS-like behaviours onto them without a lot of work.
I had a go at implementing custom taxonomies and post types on my forthcoming (soon, I promise) cookery blog. I want traditional blog-style content alongside recipe content, but didn’t feel that Pages were quite right for the recipes. I defined a new type ‘recipe’ and custom taxonomies ‘recipe_type’ (like Categories, ‘Starters’, ‘Soups’, ‘Baking’ etc) and ‘Ingredients’ (like Tags).
I followed the tutorial above, which although explains things nicely although turns out to have some spurious code. Take your code from the WP Function Reference for register_post_type() and register_taxonomy() and have a look about the general intro to Post Types.
The tutorial falls short in telling you how to get content from your new type displayed in your templates. I wanted a promo section on the home screen for recipes and used this to do it:
wp_reset_query(); /* start with a new query */
'posts_per_page' => 6, /* get me the most recent 6 */
'post_type' => 'recipe', /* get recipes, not posts */
'recipe_type' => 'soup', /*only get me ones of recipe type 'soup'
if (have_posts()) :
while (have_posts()) : the_post(); /* deal with what comes back in the usual way */
And build some navigation for your new type:
$args = array(
'taxonomy' => 'recipe_type', /* choose custom taxonomy */
'orderby' => 'name', /* alphabetical */
'style' => 'list', /* as <li> </li> */
'title_li' =>'', /* DON'T nest the title in the <ul>, that's annoying! */
wp_list_categories( $args ); /* same function you'd use to do this with normal categories */
Custom post types give you nothing that you can’t already do with Pages and Posts, so why bother?
- They lets you treat different types of things differently without lots of conditional code – if I create templates called single-recipe.php and archive-recipe.php, WP will automatically display my content of type ‘recipe’ using them. To display the archive for your post type, you’ve got to create a page then tell it to use that template – crazy huh?
- It would be easy to build a faceted search/archive with custom post types and taxonomies.
- You have control over permalink structure for types and taxonomies – though slug rewrite for my type just gave me 404 errors. I will experiment further because it would be worth getting this right.
- It might cut down complex custom fields.
- You’ll get a smug sense of satisfaction from being a purist (relatively speaking, this is still WordPress after all).
When not to use custom post types:
- You want all your content in a single RSS feed or a single archive – you’d be fighting with it (actually, this shows you where to start).
- You want the same tags or categories across all content types – make do with the build-in types.
- You only have one type of content – use the built-in types and define custom taxonomies for them.
- You want an easy life – you’ll have to work on your theme to make this work.
In summary, custom post types let you do things you can already do in a nicer way, and who knows, future releases might incorporate things like definable custom field structures.