Rock-Solid WordPress 3.0 Themes using Custom Post Types

Rock-Solid WordPress 3.0 Themes using Custom Post Types

Tutorial Details
  • Technology: WordPress
  • Topic: Custom Post Types
  • Difficulty: Moderate

The WordPress community is buzzing with excitement over the soon-to-be-released WordPress 3.0. Currently in Beta 2 now, WordPress 3.0 will have a lot of exciting new features , such as a new default theme and better menu management. Quite possibly the most exciting of these features is custom post types. In this tutorial, we’ll talk about creating and using custom post types to make a rock-solid theme.


What is a Custom Post Type?

Well, according to the WordPress Codex:

“Post type refers to the various structured data that is maintained in the WordPress posts table. Custom post types allow users to easily create and manage such things as portfolios, projects, video libraries, podcasts, quotes, chats, and whatever a user or developer can imagine.”

Essentially, it allows us developers to make new kinds of posts similar to the post and page types, which all appear in the main navigation in the WordPress admin. There are several advantages to this; most notably, we no longer need plugins to create special types, we can build a theme that relies less on custom fields (as we know them), and they make managing the site easier for clients and non-technical users. Instead of telling them to create a “post” and make sure to fill in all kinds of custom fields for say, music, we can simply tell them to click “Music” to add a new music post.

Let’s Get Started!

In this tutorial we will:

  • Create a Custom Post Type for Products with our own inputs
  • Create a custom “taxonomy” for the type.
  • Create a theme template to go along with the new type.

Register the Custom Post Type

All of this will be done from within our theme’s functions.php file. I’m modifying the default 3.0 theme, TwentyTen.

The first thing we will do is tell WordPress that we want to register a new custom type. Here’s the code:

	add_action('init', 'product_register');

	function product_register() {
    	$args = array(
        	'label' => __('Products'),
        	'singular_label' => __('Product'),
        	'public' => true,
        	'show_ui' => true,
        	'capability_type' => 'post',
        	'hierarchical' => false,
        	'rewrite' => true,
        	'supports' => array('title', 'editor', 'thumbnail')
        );

    	register_post_type( 'product' , $args );
	}

The first line is a hook to tell WordPress that we want to call the function product_register() during initialization. It’s in that function that we register the new post type.

The function register_post_type() accepts two arguments: the name we want to give our post type, and a list of arguments used to create that post type, which we put in an array called $args. You can read exactly what all of the arguments are here, but I want to point out the important ones.

  • label & singular_label: These are the labels as we want them to appear in the WordPress admin. ‘label’ will show up in the admin nav and anywhere that references multiple entries of that type (Edit Products, for example). ‘singular_label’ will show up when one of that type is referenced (Add Product, for example).
  • capability_type: This tells WordPress which native type (post, page, attachment, revision, or nav-menu-item) the custom type will behave as. By making it a ‘post’ type, we can do things like add it to a category.
  • rewrite: Tell WordPress if (or how) to apply permalinks formatting. You can send a boolean as we did, or any array of arguments to apply a custom permalink format to the type.
  • supports: This is everything on the add/edit page that will show up. We want to have a title, editor(the content), and thumbnail images. Next, we will add our own custom inputs by cleverly masking custom fields as input fields for our custom type.

Adding Our Own Inputs

Let’s add our own custom inputs for our new type. Since we can now create new post types, we can make the custom fields more streamlined for users that might not be as familiar with WordPress as we are. It’s worth noting here that this functionality has been available since 2.5 and up until this point, has been used primarily by plugin developers. Here we are going to add a price field.

<?php
	add_action("admin_init", "admin_init");
	add_action('save_post', 'save_price');

	function admin_init(){
		add_meta_box("prodInfo-meta", "Product Options", "meta_options", "product", "side", "low");
	}

	function meta_options(){
		global $post;
		$custom = get_post_custom($post->ID);
		$price = $custom["price"][0];
?>
	<label>Price:</label><input name="price" value="<?php echo $price; ?>" />
<?php
	}

function save_price(){
	global $post;
	update_post_meta($post->ID, "price", $_POST["price"]);
}
?>

Once again, the first couple of lines are hooks to tell WordPress when we want to use certain functions. The first line says that when the admin panel is initialized, call the function that we wrote, admin_init(). This function tells WordPress to add an area called “Product Options” to any posts of type ‘product’, and to use the function meta_options() to print the form fields. You can read more about add_meta_box here. meta_options() will then get any preexisting custom values and print the form field. The second action line states that when a post is saved, call our function save_price(), which uses update_post_meta() to add or update a custom field called ‘price’.


Custom Categories and Edit Columns

Our last step in creating a completely custom type is giving unique names to its category and edit column labels. First, the custom category name, or ‘taxonomy’.

register_taxonomy("catalog", array("product"), array("hierarchical" => true, "label" => "Catalogs", "singular_label" => "Catalog", "rewrite" => true));

The function we use is register_taxonomy(), which you can find in the codex here; it has been available since 2.8. It’s essentially saying that we want to create a new category type called ‘catalog’ which we will associate with the ‘product’ type. The last argument is an array of information similar to what we saw the register_post_type() function. When all is said and done, we will have the term ‘Catalog’ appear beneath our Products menu in the WordPress admin and it will behave like Post Categories do.

Next, we want to create a custom set of columns for our Product type.

add_filter("manage_edit-product_columns", "prod_edit_columns");
add_action("manage_posts_custom_column",  "prod_custom_columns");

function prod_edit_columns($columns){
		$columns = array(
			"cb" => "<input type=\"checkbox\" />",
			"title" => "Product Title",
			"description" => "Description",
			"price" => "Price",
			"catalog" => "Catalog",
		);

		return $columns;
}

function prod_custom_columns($column){
		global $post;
		switch ($column)
		{
			case "description":
				the_excerpt();
				break;
			case "price":
				$custom = get_post_custom();
				echo $custom["price"][0];
				break;
			case "catalog":
				echo get_the_term_list($post->ID, 'catalog', '', ', ','');
				break;
		}
}

The first two lines are hooks to tell WordPress that we want custom columns for the ‘product’ type. The first line says that when printing columns for the product type, use the ones defined in the function prod_edit_columns().

In prod_edit_columns(), we have a key-value array where the keys are used to reference certain post information, which we define in the second function, prod_custom_columns(). The values in that array are the column headings. You might notice that prod_edit_columns() lists five columns, but we only describe display information for three in prod_custom_columns(). ‘cb’ and ‘title’ are part of a set of default keys that WordPress already has associations for. WordPress doesn’t know what the other three are, so it’s up to us to define them.


Making the Theme Template

Not too shabby, right? And now we are finally up to the fun part- the theme template. To make a theme template for a custom post type, we simply name the template single-<post-type-slug>.php and add it to our theme. In our case, this would be single-product.php. Here I will show you a snippet of that page that displays all of the information we’ve added to our custom post type:

<?php the_post(); ?>

<?php
	$custom = get_post_custom($post->ID);
	$price = "$". $custom["price"][0];

?>

<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<h1 class="entry-title"><?php the_title(); ?> - <?=$price?></h1>

<div class="entry-meta">

	<div class="entry-content">
		<?php the_post_thumbnail(); ?>
		<?php the_content(); ?>
	</div>
</div>

I’ve added this code to the Twentyten theme in WordPress 3.0 Beta, as it’s the only theme that supports the new functionality- namely the menu system. I copied the single.php template, renamed it single-product.php and replaced everything in the ‘content’ div with the code above. To test my code, I went to Themes->Menus and added our new type to my site’s navigation. Then, I clicked through to our custom post type.


Wrapping Up

As I said previously, WordPress 3.0 is still in beta (you can get it here); so there are still some bugs to work out and some things may change in the final version. The best thing you can do is get in there and play with some of the new features to familiarize yourself with the updates/changes. From what I’ve seen so far, things are looking pretty good!

Joe Casabona is jcasabona on Codecanyon
Add Comment

Discussion 223 Comments

Comment Page 1 of 41 2 3 4
  1. The10Most says:

    Wow guys, this is awesome!
    Wordpress 3.0 really promises even more customization than previous versions.

    Thanks for sharing,
    The10most.com

    • Andi says:

      I’m looking forward to download the official wordpress 3.0 release. I tested the beta version and is very cool.
      Also, thank you Joe for this tutorial, you have explained very well the custom post type feature.

      • The new version 3.0 RC is available now. But the official release maybe will available in June. So, we have to wait ;))

        This tutorial is cool. It wraps all features of WordPress 3.0. I found something new here – the custom column view. Thanks for sharing.

      • Slobodan says:

        But none of the features will change, only some bug fixing if they find some. But those are probably some minor bugs so i guess we can start using it, no need to wait :)

  2. Jeba says:

    hmm.. custom post.. interesting :)

  3. Laira says:

    Nice tutorial…This is a great feature and very customizable. Thanks…

  4. Andrew says:

    I am glad wordpress has introduced this in 3.0, however I still feel using plugins like “Magic Fields” and “Flutter” are way easier to implement than using actual code to create the custom field. But that’s just me :D

    • I agree, but as easy as magic fields is to use, it relies on a plugin and it has it’s quirks.

      I have to admit I’m surprised custom post types aren’t slightly simpler but I’m still excited that they have added that functionality.

      Will be interesting to see the final 3.0 release

  5. piyanistll says:

    very good post thanks a lot

  6. eyal says:

    where i put the code in
    “Adding Our Own Inputs”

  7. Asker says:

    wordpress 3.0 is soooo cool………….. :)

  8. Clyde Sanchez says:

    I really like these new features in WordPress 3.0. The custom post types and taxonomies allow theme developers alot of freedom to create very user friendly themes.

  9. Matt Wiebe says:

    A fine intro to custom post types, but your information is outdated. If you read the Important changes to post type and tax registration post on the wpdevel blog, you’ll see that assigning labels and capabilities to your custom post type has changed since the information in your post was current.

  10. Have been using WP3 and am very impressed. Looking forward to implementing some of the ideas of this post. Thanks.

  11. internubs says:

    Anyone know when WP3 is due for release?

  12. Codeforest says:

    I really can not wait for the full version of WordPress 3.0. This is a new level awesomeness :-)

  13. Damion says:

    WordPress 3 just seems to look better and better, With all the customization’s this should be a great release.

  14. Jorge says:

    ufff… WordPress 3 uffffff wordless

  15. John says:

    I love WordPress. 3.0 will make things a lot more interesting. Also makes me think where it will be in 5-10 years from now..uhmmm…

  16. Kaniadona says:

    Awesome post……….
    thanks a lot

  17. Dave Porter says:

    Thanks, great article seems very powerful…

    Could someone advise where the different snippets of code go please ?

    Also just noticed RC1 was just released !

    cheers Dave

  18. Jim says:

    I don’t think that it’s anything special, well for the average user.
    Not all people want to mess with code.
    It’s nice to to give you a way to make custom content types and fields but what’s the point if i have to write code?
    I think i’ll stick with flutter for now.
    Why not to choose Drupal that you can make content types and all kind of fields right out of the box.
    Just through the admin panel.

    • Rick Adlam says:

      Hi Jim,
      The reason I feel is the ease of setup and use of WordPress versus Drupal. And I don’t agree entirely with your point.
      Basically I see there are three types of users of open source. Developers, web Designers [frontend] and non technical people who want to build a website like me. Drupal seems to lean towards the techies who want to build big sites, that use web designers for the frontend.
      Drupal is a more powerful application, but it has a few issues on usability.
      WordPress is easy peasy to set up and use. You can find plugins to do most addons of functionality,if you don’t want to stuff around with the code.
      And another thing, there are theme developers who add this fuctionality for you.
      You don’t have to be a PHP developer to set it up and use it. The code examples above would be fun to a developer, but easy for a dummy like me if I were told exactly where to put the code and in which template [things I see the smarter boys leaving out a lot, because they think its trivial.]
      I have been trying to get my head around Drupal for a couple of years.
      And you are right, Drupal has great functionality out of the box, but it requires a lot of modules depending on how you intend to use it. Not all are in “the box.”
      Drupal I understand are also moving to fix this issue with commercial bundled installs of Drupal core and modules for a give task and website, at a cost to the user.
      My opinion is that Drupal developers think differently and maybe their brains are wired differently or something, but they seem to live in a different World than me.
      They have only just realised that WordPress is growing ballistically and have now started to address the non technical user issues.
      Drupal Aquia and Drupal Gardens are other great initiatives to solve this “getting the power of Drupal into non techie hands” that I see as the core problem. But these are expensive ways for non techies to make a website.
      For some strange reason Drupal seems to think that it should be easy for someone to build a blog with Drupal. Why would you bother with Movable type, Blogger, WordPress and now Tumbr filling that space.
      But setting up the site and understanding Drupal is hard [OK, yes I'm a Dummy].
      This usability gap has been recognised by Drupal and they are trying to fix the usability issues in Drupal 7. I thought Drupal 7 was going to be released in September 2009, so I dug in and put up a couple of sites.
      I am still waiting for Drupal 7. Books that were to be launched in January are still not at the printers.
      That’s when I discovered two more problems.
      Lack of themes compared to WordPress, and very resource hungry. One site I built required upping the memory and shared hosts don’t like that.
      By the time I had finished the site I was sick of Drupal, even though it operates flawlessly.
      So if you want to run Drupal you ideally should have to run on a virtual server at least, or join Drupal Gardens, or pay Drupal Aquia for hosting, and most people can’t afford these options.

    • John Faulds says:

      That’s my thoughts too. Seems like a lot of hoops to jump through when you compare that this sort of functionality can be accomplished with a few clicks in other CMSs.

  19. Will says:

    Thanks for this tutorial, it saved me hunting things down, very much appreciated. At OneMetal we really love WordPress, and have been eagerly awaiting the final release of version 3.0. Thanks again for the tutorial.

  20. James Macfie says:

    Fantastic post – you really helped me grasp the custom-post concept. Thanks a lot

  21. wwebz says:

    Hye

    Thanks a lot for detail explanation about custom fields.

  22. Cant wait for the official release of WordPress 3.0. I’ll have to re-do a lot of the recent work I did on my theme or start over from scratch. Fun!

  23. Michael says:

    WP 3.0 Looks awesome! I hope it’s gonna be easy to add also a field for uploading an image/file. With multiple uploading functionality.

  24. sin2384 says:

    I cant wait for this to start working, things will be much easier! Great stuff, and thanks for the post!

  25. Paris Vega says:

    Exactly what I was looking for. Can’t wait for WordPress 3 full release.

  26. Christophe says:

    Thank for the article
    I have a question so about the template.

    I have created a custom type name “projects”
    when I create a new project the url is /projects/url – when I go there the correct theme file is used (single-projects.php). So no problems here

    But what i’m trying to do is create the page /projects that will list all my projects.

    I still have not figured out how to do that

    Any Ideas

  27. lpdumas says:

    Works great, except that i can’t see my custom post live!

  28. krike says:

    Thank you for this :D can’t wait for the release of the new wordpress 3.0 :) they really outdone themselves this time

  29. eliZZZa says:

    Best tutorial on Custom Post Types up to now! Thank you!
    The only thing I don’t get working is to find the New Custom Category or the Post Type in the Menu, as you said:
    Citation: “To test my code, I went to Themes->Menus and added our new type to my site’s navigation. Then, I clicked through to our custom post type.”

    Kind regards from Austria,
    eliZZZa

  30. Napir says:

    Looking forward to this :) thanks for the good article!

  31. hakem says:

    WOW , that’s really an awesome feature , can’t wait to use it on my next project

    Thanks for sharing the information :)

  32. Ether says:

    Impressive post, as always :) Thank you.

    I can’t wait for the release of version 3.0, i am already experimenting on a couple of websites i have.

    With Custom Post Types and Taxonomies, WP will become the best CMS, for any kind of website

  33. Fawad Hassan says:

    WP 3.0 is simply amazing!

  34. Rick Adlam says:

    Thanks for a great article on custom posts. I have a few WordPress blogs, and wanted to use the functionality of WordPress 3.0 for my old static mortgage site.
    Two questions.
    How could I use custom posts for this purpose? Could I use interest rates for the price analogy given above? Or is their a better way?
    Can do this in pages,not just posts?

    • Joe Casabona says:
      Author

      Rick- The example I used above is for a product (as if I were building an e-commerce site), but you can make any custom type you want with as many attributes and whatever terminology you’d like- there does not need to be an exact translation to my example.

      While they are alled “Custom Post Types” they can theoretically be anything you’d like. To give it the same functionality as a page, you would change the ‘capability_type’=>’page’ when you register the new custom type. Then it’s up to you to build the theme template for it.

      • Rick Adlam says:

        Thanks Joe.
        I notice that WP 3.0 has moved to RC1, so the release looks like happening over the next few days. I’ll wait till then and build a new site at /next site and play around with custom posts and custom taxonomies on that till I get what I need to do to create a unique site.

  35. Josh says:

    This is sweet! I have beta installed on my local server going to have a go at integrating a custom post type into my theme it could increase my work flow dramatically.

  36. Courtney says:

    Ahhhhhhhhhhhhhh, how annoying.
    I’ve wanted custom post type for sooooo long.
    My whole site uses custom posts and now they role out an official version….
    so much for an upgrade anytime soon then eh….?

  37. Matt says:

    Thanks for the tutorial! Very excited about 3.0.

    Although, I followed you’re tutorial closely, yet the information held in the newly created meta_box, such as the option “price” that you used, will disappear after time. I can’t quite explain it, but it saves it in the database for a few minutes, then seems to flush it out.

    What could cause this?

  38. go4webapps says:

    very useful.. tutorial thanks for share…

  39. adam says:

    This is exciting functionality, WordPress 3.0 appears to be getting into a full blown CMS now, which is what i expected would happen.

    For the past few years I have been focusing in WordPress as the primary CMS for clients, much of what I have been custom developing in annoying round about ways to provide even more back end user functionality will be addressed in the added loop functionality now, and i can drop some old habits.

    A comprehensive e-commerce integrated solution will be far easier and more reliable to develop now, thanks!

  40. I have just moved over to wordpress and this is one of the reasons I did not before, with this new stuff you can do so much more,

  41. Showcase WP says:

    We will use less custom fields now. WordPress is not more that simple CMS only used on blogs, people must accept that. WP is the best now, I can’t imagine one year from now. I saw that the BB Press will be a forum plugin to WP soon, so, with all these new things, WPMU, custom post types, menu manager, wow… it is really awesome.

  42. Flowreen says:

    Wow, great framework!

  43. Jason says:

    There is one thing I’ve sorta been struggling with Custom post types and taxonomies. Is there a way to dynamically list out the taxonomies on the front end? Similar to how wp_list_pages() would list out pages or wp_list_categories() would list out categories?

    So in the case of this article, say you wanted a list of links to all of your “catalogs” on your sidebar or something, how would you do this?

    If anyone can point me in the right direction as far as what function to look at, I’d really appreciate it. The only way I’ve figured out how to do it is by using the get_terms() function and then using that array to list out the links. I’m thinking there’s gotta be a better way to do it :-)

    Thanks in advance!

  44. Jim Krill says:

    Great tutorial Joe! Thanks for posting this.

    I’m super excited for 3.0 and specifically the addition of custom post types. Good stuff WordPress!

  45. Dan D says:

    Great tutorial. Very helpful and thorough on all the key points. Thanks a lot.

    So when I went through your tutorial, I encountered one small error that drove me nuts for a a bit.

    This line was causing problems:

    When it should read like this:

    Or something like that.

    Nonetheless, excellent tutorial. A big help to my current project.

  46. Matt says:

    Using this method will reset the meta box fields if it autosaves. I couldn’t figure out why it does this, so I’ve been using the Custom Post Type UI plugin and the Verve Meta Boxes plugin to get this done. Using these plugins is a little bit easier and will remedy the issue of “flushing” the meta boxes on autosave.

  47. Dan D says:

    Also, I’m getting these errors:

    Notice: Trying to get property of non-object
    Undefined index: price

    on this line (which may be related to the $price declaration):

    update_post_meta($post->ID, “price”, $_POST["price"]);

    I’m a noob, so any help would be appreciated.

    • Joe Casabona says:
      Author

      Hmm- Make sure you’re able to get the $post information- it’s telling you that $post is not an object and you are treating it as such. In the code above, I have the line global $post, which grabs the post information from the global variables.

      Hope this helps!

      Joe

  48. jeroen says:

    A great article! Here’s a related article about custom types in 3.0 that goes in a bit more detail http://justintadlock.com/archives/2010/04/29/custom-post-types-in-wordpress

  49. mike says:

    Great tutorial thanks a lot! I was wondering though, how to go about adding multiple meta boxes to the custom post type, and hence multiple custom columns (you only add one). Any help would be appreciated, I am kind of new at wordpress development. Thanks!

  50. Great Post, WordPress is involving into a great CMS system… This Custom Post Type Stuff will make life so much easier…

Comment Page 1 of 41 2 3 4

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.