Extending Custom Post Types in WordPress 3.0

In a previous article about Custom Post Types in WordPress 3.0 I outlined one of the most exciting features coming up in 3.0 and I noticed that people have already started building websites upon these new features. It’s not a secret that I’m working on a project myself which involves 3.0 so just like everybody else, I can’t wait to see it being released!

My project involves a custom post type for real estate and in this post I’d like to show you some tricks on:

  • Working with custom post types and permalinks (a.k.a the 404 issue)
  • Using WP_Query to find your custom-typed post
  • Adding custom meta boxes to your edit post screen

We’ll deal with more code than images today so get a clean copy of WordPress 3.0 (Nightly build) to experiment upon. We’ve seen the register_post_type function already which is clearly explained in the Codex and even more clearly in the source code so I expect you read those bits if you haven’t.

Permalinks with Custom Post Types

This is one side of the feature which is not thoroughly explained in the source code, and I’ve seen many people end up with 404 pages while their permalinks point correctly. The trick here is in the rewrite and _builtin part. The _builtin parameter simply tells WordPress that the new post type we’re registering is built in. Most of us specified it as true (and I did too in my previous post) as part of the code was just copied from the core part where Posts, Pages and Attachments were being registered, and those are built-in. Built-in post types are handled differently by the core, so make sure you switch that option to false.

The rewrite parameter is not too tricky if you went through the sources, it’s simply an array to specify how would you like your permalinks to look like for this specific custom post type. Let’s look at an example:

register_post_type('property', array(
	'label' => __('Real Estate'),
	'singular_label' => __('Property'),
	'public' => true,
	'show_ui' => true, // UI in admin panel
	'capability_type' => 'post',
	'hierarchical' => false,
	'rewrite' => array("slug" => "property"), // Permalinks format
	'supports' => array('title','author')
));

Straightforward. Now if you registered your custom post type this way, your edit post screen should show you the correct permalink, i.e. /property/post-name which now gets handled by the core rewrite module so you’ll be able to see the contents of your post if you click on View Page. There, no more 404 errors!

One other way around this would be to use the add_permastruct function of the $wp_rewrite object and manually define what kind of permalink structure you would like to use for your custom type posts. Don’t forget to filter post_type_link if you do.

So how about using different templates for custom post types? Well, you could do that somewhere inside your theme, but I like to hook to the template_redirect action, so here it goes:

add_action("template_redirect", 'my_template_redirect');

// Template selection
function my_template_redirect()
{
	global $wp;
	global $wp_query;
	if ($wp->query_vars["post_type"] == "property")
	{
		// Let's look for the property.php template file in the current theme
		if (have_posts())
		{
			include(TEMPLATEPATH . '/property.php');
			die();
		}
		else
		{
			$wp_query->is_404 = true;
		}
	}
}

Note: It has become much easier to use templates with custom post types with WordPress 3.1 and especially 3.2. Take a good look at the new Template Hierarchy ;)

What we did here is looked for our custom post type and redirected it to property.php located in the currently active theme (assuming it’s there of course). This part may be done in several different ways and mine’s not the best, but it gives you an idea of how to capture custom posts requests. Let’s move on to querying.

WP_Query and Custom Post Types

This is easier than you think, there’s absolutely no tricks in here, and it’s all straight forward. Just like you used to search for posts and pages, you search for your custom post name, in my case it’s property:

global $wp_query;
$wp_query = new WP_Query("post_type=property&post_status=publish&posts_per_page=5");

That’s it. Custom post types are handled pretty much the same way in WordPress loops, this means that you’re free to use template tags such as the_title(), the_permalink() and so on.

Metaboxes for Custom Post Types

Metaboxes are just as easy as queries. Just take a look at the $page parameter of add_meta_box. That’s where you have to clearly state which screen should hold your metabox. In my case it’s property, so here’s what I got:

add_meta_box("my-property-meta", "Property Options", "my_property_meta",
    "property", "side", "low");

function my_property_meta() { echo "Boo!"; }

Awesome, isn’t it! It’s also a good idea to fire add_meta_box in the admin_init hook ;) Here’s a sneak preview of what we’ve got:

Extending Custom Post Types in WordPress 3.0

I’m not sure where all this is going, but I see people getting excited about this. I see other people who don’t care and say they could do all the same stuff in the edit post page, then extend all the stuff using custom fields. That’s true, until you got a say not very computer literate client. I’d like to see somebody explain custom fields to those types ;) I didn’t manage to, maybe I haven’t got the skills, but hey, isn’t it easier to click, drag & drop, etc? I mean you do use your mouse, don’t you?

Anyways, let’s see where this goes. I’ll be working on the real estate type for some time but I’d like to hear out your ideas and perhaps some written examples of how we (the themes and plugins developers) could benefit from custom post types and make our clients a tiny bit more happy. Cheers!

Working Example: Podcast 3.0

Here’s something I’m working at and will hopefully finish this in time for WordPress 3.0. You can look through the source code to see how the Podcast custom post type is registered, the way a meta box is added to it, and the way custom taxonomy is used together with the custom columns in the edit post screen.

There’s a template_redirect action which fires a theme file called podcast.php which would be the template used to display podcasts so you’ll get an error if you don’t create such a file in your theme. Feel free to use the standard template tags inside the file, it goes as an ordinary WordPress loop.

Download: Podcast 3.0 (update:outdated) for WordPress.