Curated by Carsonified

Learn with Treehouse

Accessibility, CSS3, Design, Django, HTML & CSS, HTML5, JavaScript, jQuery, NoSQL, PHP, Responsive Web Design, Ruby, Ruby on Rails, Tools, UX, Version Control, WordPress, iOS and more

Article 191

Create your first WordPress Custom Post Type

By

30 June 2010 | Category: Uncategorized

Let me get something off my chest. WordPress sometimes, just ever-so occasionally, makes things sound a little harder than they actually are. Custom post types sound quite scary, but really they aren't. Jane Wells, WordPress UI guru, commented on their name in my last article for Think Vitamin:

"They just got named poorly because they live in the Posts table in the database. Think of them more like custom objects/content types."

Cool - it's just custom content. What's the point of that then? Can't we just categorise blog posts and order our pages in nice hierarchies? Can't we use conditionals to spit out different CSS stylesheets? Well yes, we could. But admit it – it's not fun.

And hands up if you've ever tried to explain to a client what a custom field is. Hurts, doesn't it? So thank goodness for wonderful people like Jane who have given us a solution.

What is it and What it isn’t

Everyone’s talking about them. I recently asked Chris Coyier from CSS-Tricks what excited him about WP3 and he replied custom post types:

“Think of how Tumblr works – how you can publish photos, quotes, links and whatever else. You could create those same types now with WordPress, and build themes to support and have special styles for them. This is fantastic stuff for building custom sites!”

Make sense? Well according to Jane, Chris misinterpreted their goal:

“Custom post types aren’t really meant for that use […] Custom post types are great for things that are more or less catalogued: products (in an e-commerce site), listings for a real estate site, etc. For regular content creation as described [by Chris], you can already do [that] by using custom taxonomies and/or stylesheets to make post templates.”

Now I’m going to go out on a limb here and say that Chris made a interesting suggestion. I say this for two reasons: firstly because I think the great thing about WordPress is we can use it in the way we feel it should be used. There might be a different or better way, but there is no wrong way to do something (unless it doesn’t work!). Secondly I refuse to believe that many designers would read up on something as scarily titled as ‘custom taxonomies‘.

Indeed I expect to see WordPress themes cropping up all over the place that mimic the way Tumblr themes look and work. WooThemes have already released three.

Get your Hands Dirty

Now before we dig in I want to say this – custom post types make things a lot easy for non-technical people to use the WordPress admin to enter content. However the designer/developer still needs to have a reasonable grasp of PHP and needs to be prepared to get their hands dirty (unless they opt for a plugin that does the job for you like http://wordpress.org/extend/plugins/custom-post-template/ or http://wordpress.org/extend/plugins/custom-post-type-ui/)

For our tutorial we’re going to be editing functions.php which is your theme directory. We’re simply adding to this file, so feel free to start at the top or at the bottom – just don’t change any of the code that’s already there. For the more confident of you out there you could adapt this code into a plugin.

With a few edits we are going to create a custom post type for our portfolio, and a template which will use this information. We’ll end up with a new panel in the admin menu which looks like this:

A custom post type admin panel

A new overview page called “My Portfolio”:

Custom Post Type admin page

And a new place to enter our content:

Custom post type edit screen

Step 1

Here’s the first bit of code we need to add to functions.php, which I’ll review below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
add_action('init', 'portfolio_register');
 
function portfolio_register() {
 
	$labels = array(
		'name' => _x('My Portfolio', 'post type general name'),
		'singular_name' => _x('Portfolio Item', 'post type singular name'),
		'add_new' => _x('Add New', 'portfolio item'),
		'add_new_item' => __('Add New Portfolio Item'),
		'edit_item' => __('Edit Portfolio Item'),
		'new_item' => __('New Portfolio Item'),
		'view_item' => __('View Portfolio Item'),
		'search_items' => __('Search Portfolio'),
		'not_found' =>  __('Nothing found'),
		'not_found_in_trash' => __('Nothing found in Trash'),
		'parent_item_colon' => ''
	);
 
	$args = array(
		'labels' => $labels,
		'public' => true,
		'publicly_queryable' => true,
		'show_ui' => true,
		'query_var' => true,
		'menu_icon' => get_stylesheet_directory_uri() . '/article16.png',
		'rewrite' => true,
		'capability_type' => 'post',
		'hierarchical' => false,
		'menu_position' => null,
		'supports' => array('title','editor','thumbnail')
	  ); 
 
	register_post_type( 'portfolio' , $args );
}

Anyone who’s worked with WordPress before will recognise the structure here. We’re adding an action when the WP Admin initialises to call the function portfolio_register(). In that function we create two arrays, $labels and $args, and then use register_post_type to pull it all together. In doing so we name the new custom post type ‘portfolio’ and tell it to use the arguments from $args.

The devil is in the detail, so let’s run over some of those arguments. A full list can be found at http://codex.wordpress.org/Function_Reference/register_post_type. First let’s look at $labels:

  • name this is the (probably plural) name for our new post type
  • singular_name how you’d refer to this in the singular (such as ‘Add new ****’)

You can probably work out the rest of $labels for yourself, as they simply refer to different circumstances in which the name of your custom post type would be used.

And now $args:

  • public should they be shown in the admin UI
  • show_ui should we display an admin panel for this custom post type
  • menu_icon a custom icon for the admin panel
  • capability_type - WordPress will treat this as a ‘post’ for read, edit, and delete capabilities
  • hierarchical is it hierarchical, like pages
  • rewrite rewrites permalinks using the slug ‘portfolio’
  • supports which items do we want to display on the add/edit post page

That’s the first simple step, and it should be enough to see your new custom post time in the WordPress admin. Save functions.php and take a look!

Step 2

The next thing we need to do is register a taxonomy. Or, in English, create categories for this new content type.

For example, in our portfolio we want to include the names of technologies and software used to create our work. I’m going to call this taxonomy ‘Skills’, and populate it with things like HTML, CSS and jQuery.

It’s just one line of code:

1
register_taxonomy("Skills", array("portfolio"), array("hierarchical" => true, "label" => "Skills", "singular_label" => "Skill", "rewrite" => true));

The first item here is the taxonomy name, ‘Skills’. The second is the name of the object type we’re applying it to, in our case the custom post type ‘portfolio’ (which is an array). Finally our arguments; you can find a full list at http://codex.wordpress.org/Function_Reference/register_taxonomy, and here we’re using just three which have the same meaning as described in Step 1.

Add that line of code in and you should now see:

A custom post type admin panel

You can then enter new ‘skills’ just like you’d enter categories for blog posts. It looks like this:

Custom post types - add skills

Step 3

The third step is to add custom data fields to the add/edit post page.

For our portfolio we can add things like the year the piece was published and details on who designed, built and produced the site/design.

There’s a bit more code here, but read through it in order and it should make sense:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
add_action("admin_init", "admin_init");
 
function admin_init(){
  add_meta_box("year_completed-meta", "Year Completed", "year_completed", "portfolio", "side", "low");
  add_meta_box("credits_meta", "Design & Build Credits", "credits_meta", "portfolio", "normal", "low");
}
 
function year_completed(){
  global $post;
  $custom = get_post_custom($post->ID);
  $year_completed = $custom["year_completed"][0];
  ?>
  <label>Year:</label>
  <input name="year_completed" value="<?php echo $year_completed; ?>" />
  <?php
}
 
function credits_meta() {
  global $post;
  $custom = get_post_custom($post->ID);
  $designers = $custom["designers"][0];
  $developers = $custom["developers"][0];
  $producers = $custom["producers"][0];
  ?>
  <p><label>Designed By:</label><br />
  <textarea cols="50" rows="5" name="designers"><?php echo $designers; ?></textarea></p>
  <p><label>Built By:</label><br />
  <textarea cols="50" rows="5" name="developers"><?php echo $developers; ?></textarea></p>
  <p><label>Produced By:</label><br />
  <textarea cols="50" rows="5" name="producers"><?php echo $producers; ?></textarea></p>
  <?php
}

First of all we call the add the admin_init function to the queue when the WordPress admin initialises, and within that function we add two meta boxes – places to enter our data. The context for these two statements is

1
<?php add_meta_box( $id, $title, $callback, $page, $context, $priority ); ?>

The only difference between the two is where we place them on the screen. The ‘year completed’ is placed in the sidebar using ‘side’ whilst the ‘credits’ are placed in the main flow of the page using ‘normal’.

Within the two functions there is some vanilla WordPress PHP code and HTML to help define our old friend custom fields. Make sure to include

1
global $post;

…so that we can then query the current post using

1
$custom = get_post_custom($post->ID);

Once the two new meta boxes have been added it looks like this:

Custom post types - add new post

The final thing to do in step 3 is to make sure we then save these values with this post. I do this with

1
add_action('save_post', 'save_details');

and

1
2
3
4
5
6
7
8
function save_details(){
  global $post;
 
  update_post_meta($post->ID, "year_completed", $_POST["year_completed"]);
  update_post_meta($post->ID, "designers", $_POST["designers"]);
  update_post_meta($post->ID, "developers", $_POST["developers"]);
  update_post_meta($post->ID, "producers", $_POST["producers"]);
}

There’s nothing too tricky here. Again we’re adding an action, this time to the ‘save_post’ event. It fires the function save_details() which uses update_post_meta (http://codex.wordpress.org/Function_Reference/update_post_meta) to save the relevant data.

Step 4

A nice little touch is to rejig the layout of the My Portfolio page to display some of this information. If you’ve followed through the article so far this should all make sense to you:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
add_action("manage_posts_custom_column",  "portfolio_custom_columns");
add_filter("manage_edit-portfolio_columns", "portfolio_edit_columns");
 
function portfolio_edit_columns($columns){
  $columns = array(
    "cb" => "<input type=\"checkbox\" />",
    "title" => "Portfolio Title",
    "description" => "Description",
    "year" => "Year Completed",
    "skills" => "Skills",
  );
 
  return $columns;
}
function portfolio_custom_columns($column){
  global $post;
 
  switch ($column) {
    case "description":
      the_excerpt();
      break;
    case "year":
      $custom = get_post_custom();
      echo $custom["year_completed"][0];
      break;
    case "skills":
      echo get_the_term_list($post->ID, 'Skills', '', ', ','');
      break;
  }
}

Here we’re adding two more functions to the WordPress Admin. The first, portfolio_edit_columns($columns), simply defines the columns. The first two arguments “cb” and “title” are part of the core so don’t play with those too much (you can of course rename “Portfolio Title”). It’s the next three that come from our custom post type, “description”, “year” and “skills”.

We have one more function to tell WordPress where to get this data from – portfolio_custom_columns($column). Using a simple switch/case we can define what data to actually show in the column layout. For the “description” we use the_excerpt(), for “year” we get the custom field data using get_post_custom(), and for “skills” we get a comma separated list of the terms/taxonomies/categories using get_the_term_list().

With that we have our customised columns:

Custom Post Type admin page

One final touch

Be default custom post types will display using single.php, or index.php as a fallback. The great thing is we can create our own custom template using the filename single-xxxxxx.php. In our case this is single-portfolio.php. Just create your template file in your theme directory and the custom post type will use it. How you display the data is totally up to you.

Hey, did you also notice the ‘Featured Image’ option on the add/edit page. That works out-of-the-box thanks to the ‘thumbnail’ part of:

1
'supports' => array('title', 'editor', 'thumbnail')

You just need to make sure to include the following line of code in functions.php:

1
add_theme_support('post-thumbnails');

For more details check out this excellent post by Mark Jaquith.

Rewrite Problems?

There are a few reported problems out there about the rewriting of custom URLs; in short, they sometimes don’t work. However, if you’re experiencing this problem there are a couple of easy fixes.

First, simply go to the Settings > Permalinks page, which will flush the permalinks (assuming that your WordPress install can write to the .htaccess file). This should clear up most problems related to permalinks, custom post type related or not.

If that doesn’t work you can add a line of code after you register the post type:

1
2
	register_post_type( 'portfolio' , $args );
        flush_rewrite_rules();

This worked for me on a particularly problematic install.

Conclusion

And there we have it! That is a whistle-stop tour of custom post types which I hope gives you the appetite to explore further.

The best thing is to experiment with the code, read through the documentation in the WordPress Codex, and share your ideas with others. Like any new feature I’m sure it will evolve as users create new and exciting ways to use it, and we’d love to hear about how you’re using custom post types here at Think Vitamin.

function portfolio_register() {

$labels = array(
‘name’ => _x(‘My Portfolio’, ‘post type general name’),
‘singular_name’ => _x(‘Portfolio Item’, ‘post type singular name’),
‘add_new’ => _x(‘Add New’, ‘portfolio item’),
‘add_new_item’ => __(‘Add New Portfolio Item’),
‘edit_item’ => __(‘Edit Portfolio Item’),
‘new_item’ => __(‘New Portfolio Item’),
‘view_item’ => __(‘View Portfolio Item’),
‘search_items’ => __(‘Search Portfolio’),
‘not_found’ => __(‘Nothing found’),
‘not_found_in_trash’ => __(‘Nothing found in Trash’),
‘parent_item_colon’ => ”
);

$args = array(
‘labels’ => $labels,
‘public’ => true,
‘publicly_queryable’ => true,
‘show_ui’ => true,
‘query_var’ => true,
‘menu_icon’ => get_stylesheet_directory_uri() . ‘/article16.png’,
‘_builtin’ => false,
‘rewrite’ => true,
‘capability_type’ => ‘post’,
‘hierarchical’ => false,
‘menu_position’ => null,
‘supports’ => array(‘title’,'editor’,'thumbnail’)
);

register_post_type( ‘portfolio’ , $args );
}

Follow @thinkvitamin on Twitter Please check out Treehouse

Other Posts You Might Find Interesting

  • Sorry - No Related Posts Found

Comments

  • http://www.friskdesign.com Matt Hill

    I’ve been doing some work with Custom Post Types and while I can see that they are useful for some things, I do feel that they are rather crippled from the start.

    Why? Simple, many (if not most) of the existing WP post related functions have not yet been extended to work with custom post types. So for example, there’s no ‘out of the box’ methods for handling custom posts the way you would handle standard blog posts. See here for an example: http://wordpress.org/support/topic/398135

    While I appreciate that it’s a big job to make all the existing functions work with custom post types, I do think it’s very disappointing, and a bit misleading, for a new version of WP to be released without this support.

  • http://www.4muladesign.com Jamie Brightmore

    Fantastic walk-through. I need to start playing with this feature soon for a personal project, this will come in very handy! Cheers :)

  • http://avtoio.com/ SVIT AVTO

    Wow, and in fact set out really thoughtful …
    Bookmark, think later finish reading

  • http://digitalevangelist.net Steven Grant

    I have to say when I heard about custom post types I was super excited. I love ExpressionEngine and custom fields are the huge selling point for me. However, not all projects have budget for EE and so WP3.0 looked to fit the need.

    I’ve been left really underwhelmed. Not being able to define CPTs from the control panel just seems wrong and almost ‘hacky’.

    I’d love to see 3.1 bring that power into the control panel.

  • Piet

    For the life of it, I cannot get the manage_posts_custom_column to work. By now I have tried at least 10 different possibilities including yours, but all fail to show any results.

    On my single post template get_the_term_list works as it should, but in the admin panel they just do not show.

    Any insights in that?

    Thanks!

  • http://newsignature.com Eric

    There is a that plugin makes it a bit easier to create custom post types. It’s called “Easy Post Types” and you can get it at http://www.wpeasyposttypes.com. I highly recommend.

  • http://www.e-motivemedia.com Faye

    Have been following your tutorial here to get my head round custom post types and it’s excellent – the only problem I seem to have is that the custom meta data won’t save, at least not other than the first declared type (in this case year_completed which saves no problem). Any ideas? Thanks!

  • http://www.wayneashleyberry.com wayne

    thanks for the run through, i’ve found the other tutorials very specific so this will be very helpful!

    i agree that wp3 only add the fundamental support of custom post types, it needs to be supported throughout wordpress.

    for example, the wp_dropdown_pages() function cannot access different post types, only wp_list_children can… so you’re stuck with using custom taxonomies for now

  • Vas

    Very nice post/tutorial here, thanks a lot! But if i’m a newbie i can’t really understand what i have to do after a have created a new single.php. How do i show the content from my new custom post on the site page? Thanks again.

  • http://jordankoschei.com Jordan Koschei

    I’ve already been using custom post types, but not to their full usefulness — thanks to this article, I’m able to see the full extent of their adaptability. Thank you!

  • http://jeffbridgforth.com Jeff Bridgforth

    Thanks for the article. I like how you walked through the project and explained what you were doing and how certain code worked. I wish you had done more on the template section so I could have learned how to display all the information from the custom post type you created. That would have been helpful for me to see so that I understood the whole scope of the project you were doing.

  • http://www.forepoint.co.uk Shaun Bent

    This is a great article. It reads really well and is very clear to understand.

    As with many of the others who have commented I have being using Custom Post Types, but I have found it a very difficult processes to get my head around do the lack of documentation on them. This article really beings all that information together in one place, and has shown me a few places I could do things better!

    Thanks You!

  • Cedric Neveu

    Great article! It will be very useful for my future projects with WP 3.0.

  • http://davidcalhoundesign.com David Calhoun

    Great post! Thanks for the detailed walk through. I am having one issue though. For some reason my metas are not saving. The “year completed” will save correctly, but the other will not. Any ideas?

  • sandrups

    ok, tomorrow I experience

  • steve

    Spot on Matt, it seems to be a non native feature due to the hoops you need to jump through just to get something substantial.

  • http://www.tradereadingorder.com Ian

    Yeah, I’m having a lot of similar problems at my site. Just hard to get everything working with it. Weird things, like the title not taking into account the custom ost types when figuring out how many “posts” are in a category, and so on.

  • http://grokkery.com Jonathan

    One of, if not, THE, best WP3CP tutorials out there. Thank you for putting this together so clearly.

    Jonathan

  • http://paperblackninja.com Rembrand

    That’s a very helpful walk-through. I’m currently exploring some options for my portfolio. I don’t know if this has been brought up anywhere else, but is it possible to group custom post types together like you would categories and subcategories (extended into pages and subpages)?
    E.g I have a main category Portfolio with subcategories Web, Graphic and Illustration. This gives me a full archive of everything as well as 3 more detailed archives.
    Don’t know if I can replicate that hierarchy with custom post types though.
    Any thoughts or suggestions I’d greatly appreciate!

  • http://magplazza.com Mike

    This is a long tutorial. Although I haven’t gone through the whole thing yet but thanks! A new article for beginners like us to learn about WordPress 3.0 :)

  • http://www.e-motivemedia.com Faye

    Exactly the same issue I’m having. Would love a fix!

  • http://www.richardshepherd.com/ Richard Shepherd

    Hi David & Faye!

    I’ve checked this today and can’t replicate you’re problem. I’m using a fresh install of WordPress 3 with the TwentyTen theme.

    I’ve uploaded a copy of functions.php to http://www.richardshepherd.com/php/functions.zip for you both, and this file is working fine for me. Please let me know how you go with it :)

    Rich

  • http://www.richardshepherd.com/ Richard Shepherd

    Thanks for the link, Eric.

    It seems like a lot of people are finding CPT a bit hacky, and I agree. I think it’s a step in the right direction, and it promises to be a powerful feature going forward.

    However, for the time being (like many things in WordPress) you have to roll up your sleeves and get stuck in with functions.php.

  • http://www.richardshepherd.com/ Richard Shepherd

    See below!

  • http://www.richardshepherd.com/ Richard Shepherd

    Hey Vas,

    Let’s say your custom post type is called ‘portfolio’, as it is here in the tutorial.

    1. Copy the single.php file in your theme directory.
    2. Rename it single-portfolio.php.
    3. Et voila! In this new file you can call on the custom meta data with something like this:

    echo get_post_meta($post->ID, ‘designers’, true);

    Hope that helps!

  • http://www.richardshepherd.com/ Richard Shepherd

    Hi Jeff. Have a quick look at my comment above in reply to Vas. Hopefully that’ll point you in the right direction.

  • http://www.richardshepherd.com/ Richard Shepherd

    Hi Rembrand. Sounds to me like you might need to look at custom taxonomies (basically custom categories you can create and manage) as you can arrange these in a hierarchy. You can then create pretty URLs like /portfolio/web/ and /portfolio/graphic-design/.

    Justin Tadlock has written about this in some detail, and it’s a great article. Check out http://justintadlock.com/archives/2009/05/06/custom-taxonomies-in-wordpress-28 for more details.

    Hope that helps!

  • http://www.e-motivemedia.com Faye

    Thanks Richard – have just replaced my functions.php in Twenty Ten with yours, but still having the same issue with the meta not saving. My install is an upgrade from 2.9.2 rather than a fresh install of 3.0, but that’s the only difference…

  • http://www.richardshepherd.com/ Richard Shepherd

    Okay guys, I think you just need to update the textarea code so that they have a name. For example, name=”designers” for the designers textarea etc. That should do it :)

  • http://www.e-motivemedia.com Faye

    That’s cracked it! Thanks Richard, that’s brilliant!

  • http://davidcalhoundesign.com David Calhoun

    That worked for me as well. Thanks a lot, Richard!

  • http://davidcalhoundesign.com David Calhoun

    Richard, is there a way to add a drop down menu to the view of the Portfolio posts so that I can filter the posts by these custom taxonomies? Similar to how normal posts can be filtered by category.

  • Johannes

    Thanks so much for this tutorial! I’ve gone through several custom post type tutorials but haven’t really gotten any of them working or haven’t understood them but this one is super easy to follow and does actually work perfectly.

    Exactly what I needed for a new client project I’m just starting that will be built in WP 3.0.

  • http://www.jasonagross.com Jason Gross

    Fantastic post Richard! The timing couldn’t be any better as I have been working with custom post types to build my new portfolio for the last few days. The tip about the single.php page is just what I was looking for too!

    I have noticed over the last few days that the featured image is a little frustrating to get working right as a thumbnail. In my case I want my thumbnail to be 240×110 but WordPress would much rather it be 150×110 regardless of whether I have the thumbnail size or original size option selected.

    The only way I have found to get it to work is to edit the image in WP and force the ratio to 24:11 and then force WP to let me save those image changes on the thumbnail by rotating the image once and then back, pretty weird stuff.

  • http://jeffbridgforth.com Jeff Bridgforth

    Thanks Richard for pointing that out. It is very helpful. Thanks again for writing the article. I think I am going to use it as the basis for my portfolio section my site.

  • http://jeffbridgforth.com Jeff Bridgforth

    I agree with Johannes. This is one of the clearest tutorials I have seen on implementing Custom Post Types.

  • http://jeffbridgforth.com Jeff Bridgforth

    Does anyone know if you can do other custom meta field types besides single line or text area boxes? Can you do drop-downs, checkboxes, or even WSIWYG boxes like the main content editor? I have seen it done in a plugin but that plugin has not been updated in WP 3.0 and no longer works.

    Thanks.

  • http://web-standard-design.com Trey Brister

    I tried to make your tutorial into a plugin.
    I get no taxonomies in the sidebar and an error in place of the two meta boxes

    Warning: call_user_func() [function.call-user-func]: First argument is expected to be a valid callback in /home3/conoverl/public_html/johnsoncountybar/wp-admin/includes/template.php on line 2868
    Warning: call_user_func() [function.call-user-func]: First argument is expected to be a valid callback in /home3/conoverl/public_html/johnsoncountybar/wp-admin/includes/template.php on line 2868

    Here is the pastebin of the two files the main plugin file only includes the class and nothing more.
    http://pastebin.com/CniHcGYz – Class File with your code
    http://pastebin.com/VNYwKfx3 – Plugin wrapper

  • http://www.2imagine.co.za 2imagine

    I have gone through numerous (no, a massive lot) of articles about Custom Post Types and Custom Taxonomies in WordPress 3.0 and this one is by far the best, most applicable, most correct application of said objects, most understandable, most enjoyable, most logical of all of them!

    Thank you very much Richard!

    However, it still saddens me to see that SO many people still do not see Custom Post Types for what they really are. Trapped in the mindset of a blogging environment driven by plugins and “premier” themes.

    The work of people like Richard will ease that pain.

  • http://squaregalaxy.com Jacob

    It seems that in “Step 3″ the text boxes are just HTML form fields. You should be able to use HTML (and javascript if needed) to create any sort of input widget you need.

    I could be wrong though.

  • http://squaregalaxy.com Jacob

    It seems that one of the major problems WordPress has with custom post types is that the custom content is too closely coupled to the display of it in the theme. You create a custom type like product (in an e-commerce site) and in order to display the price, you have to modify your theme. That makes it hard to switch themes, or to package up your e-commerce content types as a plugin to share with other people.

  • http://www.hppavilionstore.com Dallas Moore

    Richard!

    First of all, thanks so much for the amazing tutorial! I now consider myself a regular follower of this blog!

    As for it working, I’m doing great until I get to Step #4! For the second line what should I replace ‘manage_edit-portfolio_columns’ with? I’ve tried several things, and my new columns aren’t showing up. Help, Please!

    Dallas

  • http://www.just4freaks.de Markus
  • http://www.paperblackninja.com Rembrand

    Great! I read bits and pieces about taxonomy earlier but that possibility didn’t seem to register with me for some reason :P
    I’ll check that out, thanks!

  • http://sideradesign.com paul

    I’d recommend reading this article before deciding to use custom post types in your next project:
    http://ottopress.com/2010/wordpress-3-0-and-custom-post-types/

    There’s a better solution if you just need extra fields, you can create custom meta boxes which will be less “scary” to the client rather than creating a custom post type.

  • http://jeffreybrianfisher.com Jeffrey Fisher

    Hi Richard,

    Your tutorial is great! Thanks so much. However, I’ve created single-portfolio.php and really have no idea where to go from here. How do I access this new page. My home page posts defaults to index.php, but how do I go about setting up this new Portfolio page on which I will add these new custom posts? I read all your other replies, but I must be missing something. I am quite new at the WordPress game. Can you help or could you recommend a page in the codex? I’m not sure what terms I would search.

    Jeff

  • http://www.jasonagross.com Jason Gross

    I can not for the life of me get my permalinks to work for my custom posts :( The only way to get everything working is to use the default permalink format, otherwise my custom post types display a 404 page.

    I have tried reloading my permalinks a bunch and the flush_rewrite_rules(); line doesn’t appear to have made any difference.

    Anyone having similar problems or have I done something wrong somewhere along the line here?

  • Jason

    Awesome!

    One problem though, my “.html” permalink setting doesn’t apply to custom-post-type posts. (But does to regular posts.)

    Would you know if there is a way to fix this (add .html) via functons.php?

  • http://scottelkin.com Scott Elkin

    How do you view all posts by the custom post type you define?

    If my slug is ‘portfolio’, this will work:

    /portfolio/my-first-post/

    But this will not show all my portfolio posts and just 404′s:

    /portfolio/

    What do I need to do to make this work?

    My permalink settings are just to /%postname%/

  • http://www.goodbytes.be Joris

    Thanks for the clear tutorial. Just like some people already pointed out in the comments, I as well think this is an overly complicated and unattractive way to build custom post types. I’ve been using Expression Engine for a couple of years and they really make it dead-easy to create any type of content for me or my clients. Until WordPress has an easy and built-in way to create custom content types, I’m sticking to EE for anything that’s not a blog.

  • http://www.eriktdesign.com Erik Teichmann

    Jason–

    To use image sizes other than the built-ins, you need to first define them in your functions.php
    Use code like this:

    ‘home-post-thumbnail’ is a nickname for the size of the image. It can be anything you want.
    420 is the width, 280 is the height. The last boolean value lets WordPress know if you’d like to “hard-crop” the image. If it is set to true, the image will be cropped to exactly the size you’ve set, similar to how WP’s built in 150×150 thumbnails work.

    To use the image in your theme, use something like this:

    Hope this helps!

  • http://www.eriktdesign.com Erik Teichmann

    Sorry, code got stripped.

    Define image size:

    add_image_size( 'home-post-thumbnail', 420, 280, true ); // Homepage featured article thumbnail size

    Display image:

    the_post_thumbnail('home-post-thumbnail');

  • http://www.eriktdesign.com Erik Teichmann

    +1

    I’ve been trying to figure out the same thing. The workaround I’ve come up with so far is to use a page with an identical slug, then build a page template on that page that displays the custom content. Use code like this on that template:

    $loop = new WP_Query( array( 'post_type' => 'staff_directory' ) );
    while ( $loop->have_posts() ) : $loop->the_post();

    This isn’t pretty, but it works. The problem is, it could easily be borked by a client who wants to edit that content.

  • http://www.cippodesign.com Cippo

    Hi Richard, thank you for your tutorial :)
    I have one question. What if I want to display the portfolio loop in a page?
    How can I do that?

  • http://www.cippodesign.com Cippo

    I managed to solve it in a way. I’m still working on it but here’s what I did: I renamed a page to page-portfolio.php

    and inside it, I placed the following code:

  • http://www.cippodesign.com Cippo

    I managed to solve it in a way. I’m still working on it but here’s what I did: I renamed a page to page-portfolio.php

    and inside it, I placed the following code:

  • http://www.cippodesign.com Cippo

    query_posts(‘post_type=portfolio’);

    //The Loop
    if ( have_posts() ) : while ( have_posts() ) : the_post();
    the_content();
    endwhile;

    endif;

    //Reset Query
    wp_reset_query();

  • http://scottelkin.com Scott Elkin

    Correct, that is exactly what I did – it just felt like a hack.

  • Jaap

    Hi,

    This works very well. When I try to create another custom post types with new custom fields my page turns blank. Could you please show how to put 2 custom post types into the functions.php file?

    Kind regards,

    J.

  • Justin

    I was having the same problem as others described above with some meta-data not saving (a few minutes after I would save a custom post type along with meta data, the meta data would disappear from the WP-admin screen…), and I solved it by checking whether or not WordPress is autosaving. If anyone has the same problem, try changing the save_details() function to:

    function save_details(){
    global $post;

    $post_id = $post->ID;

    // to prevent metadata or custom fields from disappearing…
    if ( defined(‘DOING_AUTOSAVE’) && DOING_AUTOSAVE )
    return $post_id;

    update_post_meta($post_id, “year_completed”, $_POST["year_completed"]);
    update_post_meta($post_id, “designers”, $_POST["designers"]);
    update_post_meta($post_id, “developers”, $_POST["developers"]);
    update_post_meta($post_id, “producers”, $_POST["producers"]);
    }

    More info here:
    http://stackoverflow.com/questions/2539951/wordpress-add-meta-box-weirdness

  • http://www.cippodesign.com Cippo

    One more thing.

    If I use this:

    register_taxonomy(“skills”, array(“post”), array(“hierarchical” => true, “label” => “Skills”, “singular_label” => “Skill”, “rewrite” => true, “query_var”=>true, “rewrite”=>true));

    It shows me the skills in page using the echo get_the_term_list($post->ID, ‘skills’, ‘Skills: ‘, ‘, ‘, ”)

    but if I use register_taxonomy(“skills”, array(“portfolio”), array(“hierarchical” => true, “label” => “Skills”, “singular_label” => “Skill”, “rewrite” => true, “query_var”=>true, “rewrite”=>true));

    using the same get_the_term_list doesn’t show anything while the get_tag_cloud works.

    Also, your suggestion echo get_post_meta(the_ID, ‘designers’, true); doesn’t work.

    Any suggestions, please?

  • http://www.cippodesign.com Cippo

    Ok, managed to make it work.

    use this:

    echo get_the_term_list($post->ID, ‘Skills’, ”, ‘, ‘,”);

  • http://www.cippodesign.com Cippo

    Thank you very much for your article :)

    Here’s what I did with your help: http://cippodesign.com/cippo-design-portfolio

    Cheers

  • Aaron Davidson

    Solid tutorial, but after seeing how much work would be involved, looked hard at alternatives.
    Tried all the custom post type plugins (at this point in time) – some have definite potential.
    But decided that although far from ideal, Magic Fields http://magicfields.org/ along with Custom Post Template http://wordpress.org/extend/plugins/custom-post-template/ will probably get you closer, quicker. to what you thought Custom Post Types would deliver than what it currently delivers.

  • Aaron Davidson

    Touche!
    And keep posts as what WordPress does best.

  • Christoph Mandl

    Thanks for the tutorial! The custom data fields i added are created in the database for every page that is saved, even if it’s not the custom post type. Is that normal behavier?

  • Kim

    Nice tutorial.

    I’m currently working on a project and I might try getting it done with custom posts, but I’m not sure that’s the wright way to go. So I was wondering if anyone could give me a tip.

    The project is a survey with lost of different types of questions (open answers, multiple choices,…) and each question belongs to a category. On the frontside, the users must fill in the questions and get a indication afterwords. So the answers needs to be saved also, to be visualized in a chart.

    Building a custom type called ‘questions’ with hierarchy for the categories isn’t the problemen. I want to add a metabox with the ability to grow dynamically (for the answers), something like the custom fields-metabox where you can add multiple custom fields without reloading the page.

    Can someone point me to a tutorial to build a ‘custom fields’-like metabox?
    Or should I build a plugin for the whole survey app, knowing that the score also needs to be saved?

    Thanks in advance for your input.

    And thanks for the great tutorials.

  • http://www.odharma.com iamronen

    Hello Richard,

    Thank you for this great guide.

    I created a full and working custom post-type application – and in doing so I encountered a problem with the save_details() function (unless I missed something). I think that the function needs to be qualified for the custom post type – so that empty fields are not creating for other post-types (this action is not post-type specific). I added an if statement and that solved the problem:

    if ( get_post_type( $post ) == ‘portfolio’ ) {
    // update meta data
    }

    My application required automated title generation – and that messed up other posts – which is what led me to this solution.

    More on my application and tips:
    http://www.odharma.com/2010/07/creating-a-teachers-directory-with-wordpress-3-0/

    Again – thank you for the wonderful guidance.

    All Things Good
    Ronen

  • Chad

    Hi,

    First of all, great article, very detailed indeed!

    However, not sure if this is a bug or an error on my part?

    Theres a few “headers already sent” errors that appear due to the html being written out within the functions.php file?

    For example, when uploading an image!

    Any help would be appreciated :)

    Kind regards,

    Chad

  • http://john.onolan.org JohnONolan

    I agree with you on that specific issue (archive templates) Matt, and it was actually me who submitted the official ticket for that to be included in 3.1 – see http://core.trac.wordpress.org/ticket/12974

    I don’t think it’s at all misleading for any opensource (read: free) software to do (or not do) anything at all to be honest. Custom taxonomies have been in WordPress since version 2.8 and are only just now getting a front end to make them useful in 3.0. Is that misleading too? Nope, it’s just evolved over time, as everything with WordPress does.

  • Richard Frost

    Really great tutorial, thanks for putting it together.

    I’m struggling on the last bit, which pulls together the custom post information into columns. On loading the custom section in the admin screen the columns display, but only show empty spaces. If I then, go into quick edit mode for a post, and save, the information will then show in the columns for that post alone.

    Any ideas why it might do that?

  • Richard Frost

    Small update. I turned hierarchy off in the options for the custom post type and the information displays in the columns. Is there some way to enable the hierarchy mode and allow the information to be displayed in columns?

  • Richard Frost

    Fixed!

    For hierarchy to work, it seems ‘manage_pages_custom_column’ is needed instead of ‘manage_posts_custom_column’. http://core.trac.wordpress.org/ticket/14004#comment:3

  • Chad

    Nevermind,

    Had some white space after the closing php tag ;)

    Kind regards,

    Chad

  • Sean

    in your step 4, is it possible to order the list by ‘year completed’ ?

  • http://www.hppavilionstore.com Dallas Moore

    How would I do things I would normally do with categories? Is there a tag similar to wp_list_categories, or the_category that I could use. Especially the last, so that I can include the category as part of the meta information at the bottom of the post.

  • Christoph Mandl

    Thank you, that solved my issue posted above….

  • http://www.bexxie.com Bexxie

    Thanks Richard for the fantastic tutorial! I’ve read quite of a few on custom post types and this one has definitely been the most helpful. Also, thanks for posting a link to the full functions.php file. I was having a few issues but after looking at that I now have a fully functioning music discography with label, artists, catalogue number and release date. I just have to add images now.

    Thanks again!

  • http://www.charlottecoleman.co.uk Charlotte Coleman

    Thanks for a really insightful post. I’ve been wondering how to alter the layout of the custom post type admin pages and the list of post types and there don’t seem to be many tutorials out there. It’s much better to write the code in the functions file than rely on someone else’s plugin too. Great advice – thanks again!

  • Jason

    I just use the CMS Press plugin. It automatically sets up templating for this. Just create index-portfolio.php, single-portfolio.php, etc. The plugin even lets you set up pretty permalinks ending in .html, if you use this like I do. And this I haven’t found in any other post type plugins.

    The one and only major thing CMS Press is missing right now, IMO, is tag and category support. Although he does have taxonomy support. Tags & categories are on his to-do list he says. I hope it comes out SOON!

  • http://thecorkboard.org Kyle

    Beautiful!

    I’ve read a slew of posts and scoured the codex for information on custom post types as I need to write about them in an upcoming publication. This has been the /best/ resource as of yet!

    I need clarification on one thing – an item I can’t find an answer for anywhere. In this what does the “[0]” do?

    $year_completed = $custom["year_completed"][0];

  • todd valentine

    Does anyone know why the meta box values I’ve created for my custom post types are showing up as custom field values in my ‘edit page’ admin area. They aren’t there when I add the page, but after I have published the page, they show up when I go to edit the page. I substituted the $page variable in the add_meta_box function with my custom post type, so not sure why their showing up in my pages? Has anyone else experienced this? I think it could be confusing for clients.

  • ram

    Thanks for the great tutorial.
    I would like to create a portfolio in which I need child pages like “webdesign”, “logo design” and “SEO” etc. How can we achieve this target? can we do it with custom post type or taxnomies? any body can point me to tutorial?

  • http://www.multiblah.com/ Kevin Cannon

    I have the same problem as Jaap, the page turns blank as soon as I put your code it the admin presents a completely blank page.

    I’ve reinstalled WordPress from scratch and can’t find the problem. I’ve tried different code for custom post types as well as editing functions.php in different editors. I’m running wordpress on my local machine under a MAMP setup.

    Have you any ideas what it might be?

    Thanks.

  • http://inewforest.com Rich Senior

    Regarding: “Also, your suggestion echo get_post_meta(the_ID, ‘designers’, true); doesn’t work.”

    I found that too. I copied and pasted it from Richard’s comment using my text editor (Coda). However, when I looked at the single.php from within the WordPress appearance editor the single quotes around designers were showing as errors/question marks. Deleted the single quotes and replaced them and all is now hunky dory.

  • Jenny

    After reading a dozen or so tutorials on how to create custom post types I FINALLY got it and it’s working – amazing stuff!

    Thanks a lot!!!

  • Chris

    Perfect! Exactly what I was looking for… thanks for this!

  • Chris

    Correct me if I am wrong… but are you saying that you cannot use hierarchical for the Skills?

    Meaning you cannot use custom post types that make the url /portfolio/css/ ?

  • http://www.multiblah.com/ Kevin Cannon

    Solved my problem. I was editing the main wordpress functions.php rather than the one for the current theme.

  • David

    OMG a simple change:
    ‘manage_pages_custom_column’ is needed instead of ‘manage_posts_custom_column’.

    I was trying to work this out for days!

    Thank you
    Thank you

  • Alice

    I’m having the autosave issues. I tried the code provided by Justin above, but no luck. The autosave doesn’t save my custom fields…

  • Louisa

    Hello!!!

    Brilliant tutorial! I finally have a grasp on the whole custom post idea! Thank you!!!

    Just one question…
    How do I add multiple post types, say for example a design and a photograhy post type rather than just a portfolio one?

    Thanks for any suggestion!
    Louisa

  • http://www.richardshepherd.com/ Richard Shepherd

    Thanks Justin – well spotted!

    Yep, it’s a ‘feature’/'bug’ that you can read more about at http://core.trac.wordpress.org/ticket/10744 and http://codex.wordpress.org/Function_Reference/add_meta_box#Example

    I recommend your solution – checking to see if it’s an autosave or not.

  • http://www.richardshepherd.com/ Richard Shepherd

    Hey Alice – you might find your solution at http://codex.wordpress.org/Function_Reference/add_meta_box#Example

    Hope that helps!

  • http://www.richardshepherd.com/ Richard Shepherd

    Hi Louisa,

    Just rinse and repeat! You’ll need two register_post_type() ‘s, each with a different name and relevant arguments.

    Another solution would be to create a couple of new taxonomies/categories, so within ‘portfolio’ you have ‘design’ and ‘photography’ – each of which can have child categories.

  • http://www.easilyamusedinc.com James Tryon

    From what I understand the [0] stand for the first instance of that element. If you had 2 and you wanted to target the 2nd one you would use [1]. The counter starts at “0″.

    -James Tryon

  • http://www.easilyamusedinc.com James Tryon

    Yep that fixed it for me too.
    Great Review.

  • Louisa

    Thanks so much, Richard!

    Works brilliantly!! But I’m going to have to ask how I can now add new “add_meta_box” to add different categories to the ‘design’ area ! Sorry to have to ask! Trying to also get a grasp on php too at the moment but everything I tried just ended up in a blank page! Sigh!

    Sorry to have had to ask another question especially when your tutorial is so clear and easy to follow!!

  • Louisa

    Ignore my last question! I worked it out!!!

  • Jenny

    I was about to ask the same question – thanks for posting the fix :)

  • Jenny

    I have the exact same problem, and so far no fix for it. Deleting them won’t help, after saving they’re back. I agree, it’s very confusing for clients.

  • M

    Great starting point to get into custom post types.

    However, there are some potential issues that could be avoided easily, to do with naming conventions for functions, variables and also for the post types and taxonomy terms. Looks like most of them are mentioned in the comments in some way or form, but I thought I’d summarise it somewhat, having just gone through the whole thing for a site I’m building:

    As a general rule, you should give your post type a name that is unique and also different to the labels you’re going to use on the site, like ‘mysite_portfolio’, in order to keep the code tidy and to avoid a bunch of issues. You can still have nice permalinks by replacing ‘mysite_portfolio’ in the rewrite option.

    Similarly, taxonomies should get their own name. Something like:
    register_taxonomy(“mysite_portf_skills”, array(“mysite_portfolio”), “label” => “Skills” (etc…)
    I was being stupid when I first played around with this: I chose “Type” for one of my custom taxonomies, which was already used by the system (or by some plugin). Big mistake, better to avoid this from the start by giving it a unique name.

    This also helps with finding out where you have to repeat a chosen name in the code, eg when it comes to tying a taxonomy or a meta box to a specific post type.

    add_action(“admin_init”, “admin_init”);
    Not such a great idea, either. The last bit can get its own name (with the same name repeated for the function that follows).
    Otherwise people might get into trouble when they try to include several post types.

    A different but related (permalink) issue is the following:
    Suppose you want to display 50 portfolio items on your site under the name ‘Portfolio’ (naturally), with 10 items on 5 pages. Naming the WordPress page ‘Portfolio’ and the post type ‘portfolio’ is likely to get the pagination messed up.
    Choose something different for the post type (or the post type rewrite slug) and the page on which you’re calling the list of items.

    I’m no expert (please treat my points as hints or suggestions, nothing more), in fact I needed a tutorial like this to even get me started on custom post types – so full credits to Richard. I just wanted to share what I had found and how I solved it.

  • http://www.oakinnovations.co.uk/ Simon

    I’m trying to figure out the same thing. I’ve got all the the custom post type functionality working except for this. i figured using something like category-postype.php would work, but it doesn’t.

    I can see that Erik’s solution will work, but unfortunately not if you are planning to release a theme. I can’t seem to find the solution to this anywhere, so I’m starting to wonder if it’s possible without a hack.

  • Alice

    Thanks, Richard.

    I tried it, but encountered other issues. I’m not familiar with the whole nonce thing. I posted my code and issues here: http://wordpress.org/support/topic/problems-with-autosave-and-custom-fields?replies=2

  • http://haslayout.com Jason Carlin

    I’m not sure, but I think you might need to use get_the_ID() instead of $post->ID when you’re working inside the single-portfolio.php file.

    Amazing tutorial, btw. This got me further faster than anything else I was able to find online!

  • http://24design.net/ Cor van Noorloos

    Hi Richard,

    Thank you very much for this article.

    As a new guy on custom post types I wondered why _x is placed in front of ‘name’ => _x(‘My Portfolio’… instead of __?

  • Devin

    Nice walk through Richard!

    I built a portfolio theme that is very similar (minus the metaboxes) and wanted to share a real life example of the code: http://wptheming.com/2010/07/portfolio-theme/

  • http://www.friskdesign.com Matt Hill

    I should clarify up what I mean by “misleading”.

    Custom Post Types have a poor name. They should have been called “Custom Content Types”. CPT act more like WP Pages, than Posts. All the advance advertising of CPT that’s happened in the last 6 months never really made it clear that CPT are not in fact Posts, they don’t behave like them, and they don’t work with most of WPs current post related functions.

    It’s reasonable for someone to read the phrase “Custom Post Types” and think “Great! All the power of normal Posts, but I can customise them too!”. But of course, this is far from the truth.

    The fact that CPT don’t work with most of the Post functions in WordPress won’t be apparent to most users until they actually start to use them. That’s what’s misleading.

  • http://www.3roadsmedia.com 3 Roads Media

    Great article Richard. There are a lot of tutorials on how to use custom post types, but I’ve found yours to be the most intuitive and complete. Thank you!

  • http://www.3roadsmedia.com 3 Roads Media

    After following this tutorial, I couldn’t get a couple of things to work. The permalinks will not work with the register_post_type() and arrays outlined in a function; I simply removed this and permalinks worked fine.

    Also, your save function didn’t work for me. I found another tutorial that does work.

  • http://justintadlock.com Justin Tadlock

    *Some* post-related functions might not work with custom post types, but that’s a long way from “most.” In fact, nearly all post-related functions work with custom post types. But, some things are meant to be, well, “custom.”

  • http://ckaufman.com/ Chad Kaufman

    I am having problem with ‘hierarchical’ posts (note: NOT hierarchical taxonomy).

    Everything is running fine, but when I make ‘hierarchical’ => true my admin screen columns disappear. The data remains saved, but they disappear from display. When I make ‘hierarchical’ => false again, they come back.

    Any ideas?

  • http://gaberosser.com Gabe Rosser

    Having a little trouble with this. Using ID, ‘featured_vid’, true); ?> to get ‘featured_vid’ to display & it’s not working. I’ve followed the instructions & have everything on the backend, just need to figure how to display. I am a little new to this also :) Any help would be appreciated. Great post!!!

  • http://doede.net Jasper

    I have the same 404 issues. And I tried the tip mentioned here on the issue. I am wiring about it here. My .htaccess seems ok and I can create custom post types and taxonomies, but when I click view portfolio item I get this dreadful 404..

  • http://www.idwebandprint.com Delwin Holeman

    This has me stumped as well. Did you ever have any luck figuring this out? I’ve tried all sorts of things and nothing seems to work.

  • Shane

    Excellent tutorial for the most part!
    But I find it to be incomplete in the sense of displaying the custom post types on the front end. Other than the lack of explanation there, it is a great tutorial.

  • http://dougdraws.com Doug C.

    Nice in-depth tutorial, but I’m no coder so it was mostly Greek to me. I need to create a way for my client to list items on one page, so someone suggested I make a template page and then make custom post types and custom fields. None of which I know how to do.

    If it’s confusing for me then I know it won’t help my client. I might try that Easy Post Types plugin. It looks more usable than all the others. But again, the end result must produce something that my client can easily use.

  • http://lincolnbryant.com Lincoln

    You saved my life ->> This is key.

  • http://www.tradiart.com TradiArt

    Hello!

    This is a very useful tutorial. Thanks for sharing.

    Just in case it is possible… In my website I have a lot of custom post types, and I would like to filter them, in admin area, by custom taxonomy.

    Will be nice to show a dropdown of the custom taxonomies assigned to portfolio projects and when selecting one option in dropdown, only see the portfolio projects assigned to that custom taxonomy.

    I have searched to find a solution with no success… any idea if this can be done?

    Thank you!!! :-)

  • http://www.lidee.be Peter

    Nice tutorial, best I’ve seen.

    Quick question:
    I added jQuery UI datepicker (http://jqueryui.com/demos/datepicker/) to one of the inputfields in a custom meta_box for a custom_post_type.
    But, how do I get the Jquery scripts, needed for the datepicker, to load on my edit-custom-post-type only? (the jQuery UI interferes with the dashboard)

    Currently, I’m using this:
    add_action(‘add_meta_boxes’, ‘enqueue_datepicker_scripts’);
    and it works but this will load these scripts on all meta_boxes so it’s not THE solution.

    What’s the correct solution to this?

  • http://www.dentalheroes.com Cory

    I’ve adapted this tutorial to satisfy my requirements, and it’s working beautifully. However, I’m stuck when trying to display the custom meta data in my single-x.php template. I tried your suggestion for doing this to no avail. Any ideas? Thanks!

  • Harvinder

    I’ve followed this tutorial and it worked perfect!

    On the front-end, is there a way to display a list of all the categories that belong to the custom post type I created? I’m setting up a directory and would like to simply display all the categories and how many posts are under them.

    Any easy way to do this?

  • http://pulse.yahoo.com/_PB7SMCJ42ATSQNK6INJJMFMNJI Richard Welch

    test

  • http://pulse.yahoo.com/_PB7SMCJ42ATSQNK6INJJMFMNJI Richard Welch

    Hi there, I have followed this tutorial and found it very useful. I have read quite a few articles on the subject of custom post types and found this one particully well written.

    I have one issue though: I am having trouble getting any of the ‘Design and Build’ credits showing up on the front end. It looks like everything is working ok in the back end – data is saved and is displayed in the custom columns ok. I have the individual custom posts setup to use single-portfolio.php . Is there some code that I could have missed out anywhere to get the ‘Design and Build’ and also ‘year completed’ to show up on the front end?

    Cant anyone help?
    RIch

  • http://twitter.com/animegio Giovanni Wassen

    Thanks, this is just what I needed to make a box for the answers for a quiz I’m building.

  • http://twitter.com/skimbutweets Alberto Ziveri

    Best tutorial about post types I ever seen.
    This will help me to create a unique, original theme with the best design.

  • Shane

    A satisfactory starting point, but as others have commented, there are issues with the code you have posted.

    With their help, I’ve managed to sort things out.

  • http://twitter.com/resztang Victor Resz Tang

    I just have one question. Everythings working but how do i show all my portfolio items in a page?

    I cant figure out how to connect my new page with these items.

  • Anonymous

    This popular product incorporates the innovation of our Lilliput 8 Inch Widescreen LCD Touch Screen Monitor With Speakers models along with a 5-wire resistive Touch-Screen panel. Use the convenient touch-screen as your input device, control your mouse cursor or the mini on screen keyboard that comes with your operating system. The touch screen utilizes the USB porthttp://www.wholesaleeshop.com.au/laptop-battery/
    as the interface. You can connect several 700TSV monitors to your computer and the Lilliput 8 Inch Widescreen LCD Touch Screen Monitor With Speakers would work simultaneously through the multi-monitor support.

  • http://twitter.com/ideric Eric Sopp

    Massive post. Very helpful – thank you!

  • Nobodyspecial

    But wait, how to display these items on my portfolio PAGE? :)

  • http://www.techbrij.com Brij Mohan

    Nice Post!!!

    I have created a project collection theme based on this custom post type feature.

    See following to download:

    http://www.techbrij.com/342/create-project-collection-theme-wordpress-3-custom-post-type

  • Anonymous

    Best custom post type article I’ve come across. I was struggling with a few things just working from the codex but after 15 minutes through your tutorial I’m 99% done with the setup of the site I’m working on. Stellar work – thanks for sharing!

  • http://twitter.com/DreeBean Darlene

    Why is it when I go back to edit a custom post, my custom data fields are empty and are removed from the database? Can someone please help me with this.

  • Bartkurt

    Well, I’ve got a major problem with this code. I hope I’m doing something wrong and everything is fine above, but have you guys tried to display posts having certain skill (like displaying posts of specific categories)? Because I’m dumping everything from get_taxonomy() and guess what… The taxonomy is empty. I’ve checked my MySQL database – same. “Count” row for Skills is always “1″.

    How to fix that?

  • Bartkurt

    Additionally feature doesn’t seem to work here. Code like shows everything after, not before tag. And never shows more button.

    I suggest you to create custom post types on your own, because this tutorial won’t get you nowhere…

    Thanks.

  • Bartkurt

    “READ MORE” FEATURE. Christ. I’m not even able to write more tag even with slashes…

    And now when trying to reply my own messages I’m getting this error:

    “Application error: error”

    Love this blog… LMAO :) Well done…

  • http://twitter.com/dashaluna Dasha Kropotova

    Hello Richard,

    Great article, thanks a lot! I was wondering if you have worked with hierarchical custom post types at all? I’m looking into adding new records of one custom post type within another (similar to CD info, where CD is one post type and I’d like to add severla Track recods – another custom post type). Hope that makes sense.

    Are there any useful resources you came across? Would really appreciate any help :)

    Thanks again,
    Dasha

  • http://twitter.com/JakeGonzales Jake Gonzales

    I don’t know if anyone answered you but I think your problem will be something to do with the final part of ‘Step 3′ where the values are saved. This was confusing me as well.

  • http://psdtowpconversion.com Tsquez

    Probably the best tutorial on custom post types available….thank you very much

  • http://pulse.yahoo.com/_LKIL33UH5TFUAGTLRGUGH72BN4 Jamie Thompson

    Great stuff!

  • http://twitter.com/wwaldon william waldon

    Awesome post. Am using some of the features from your examples to build the current site I’m working on. YOU ROCK! Thank you!

  • http://theWebalyst.com/ Mark the Webalyst

    A longshot: I’m writing a simple e-commerce plugin (for Google checkout) and am stuck.

    Do you know how to make a custom post type for which is_page() with return true?

    I want the default handling of my custom post type to be the same as for Page rather than it be treated like a Post – but without having to modify the template (i.e. something the plugin which creates the custom post type can set).

    Thanks,

    Mark

  • http://www.nabito.net Roman Ožana

    Awesome post, thanks !

  • http://twitter.com/fxbenard fxbenard

    check your step 3, i had the same problem and i fixed it with this code

    add_action(‘save_post’, ‘save_details’);

    function save_details($post_id){
    global $post;

    if ( defined(‘DOING_AUTOSAVE’) && DOING_AUTOSAVE )
    return $post_id;

    if (isset($_POST["year_completed"]) && $_POST["year_completed"] ”) update_post_meta($post->ID, “year_completed”, $_POST["year_completed"]);
    if (isset($_POST["designers"]) && $_POST["designers"] ”) update_post_meta($post->ID, “designers”, $_POST["designers"]);
    if (isset($_POST["developers"]) && $_POST["developers"] ”) update_post_meta($post->ID, “developers”, $_POST["developers"]);
    if (isset($_POST["producers"]) && $_POST["producers"] ”) update_post_meta($post->ID, “producers”, $_POST["producers"]);

    }

    Good luck and thanks to the author for this great article

  • http://nielsencreativemedia.com Erik Nielsen

    Hey, I’ve compounded your lesson (which is one of the best on the web) into a plugin. Let me know what you think:

    http://nielsencreativemedia.com/blog/how-to-develop-a-custom-post-plugin-with-unique-taxonomy-and-tags

  • http://carsonified.com Ryan Carson

    Thanks Erik!

  • http://www.facebook.com/veeroo18 Veerendra Tikhe

    wow .. nice tutorial .. would like to get my hands in code.. ;)
    will hit you back when i get struck !!

  • Karen

    Thanks! That was a great help!

  • Dongre Developer

    Awesome Topic!!!
    Thank you so much !!!!!!!!!!!!!

  • Paul

    Hi,

    Great Post!!!

    1 question: How to use the regular WP categories in the slug.
    It is currently displaying the custom post type name and then the post itself.

    Is there a way to get the category variable into this….

    ‘rewrite’ => array(‘slug’ => ‘category’, ‘with_front’ => false)

    ????

  • Jtwillard

    Thanks Richard and thanks Justin! This code fixed the updating meta box issues :)))

  • Jtwillard

    This worked but is displaying blank columns in the browse page of the CPT…

  • http://thecountrysideisforcows.com Fausto G Pacheco

    How can I put a label categories on the info panel os the custom post types of each custom post?

  • Nicole

    Thanks for posting the functions.php file. I was having problems getting the meta to save but I replaced my functions.php with yours and now it’s working.

  • Nicole

    Using the functions.php you posted in the comments, I have one custom post type functioning properly, but I’m having trouble creating a second one. If I just copy/paste all of the code relevant to custom post types (everything inside the ‘set up a custom post type’ comment in functions.php, I get this error in chrome: HTTP Error 500 (Internal Server Error): An unexpected condition was encountered while the server was attempting to fulfill the request., and a blank page in other browsers.

  • http://www.seteado.cl Manuel Alarcón

    wow! just what I was looking for. I’ve found other articles, but none so complete and clean like this. Thanks!!!

  • Anonymous

    This was so amazingly useful! Thanks so much for this. Made one hell of a portfolio theme thanks to this (still finishing up but still).

  • Mk

    I got this error and have not been able to find the solution yet

    Call to undefined function add_meta_box()

    Thoughts?

    Thanks.

    Matt

  • Mk

    Got it. My bad. I copied something that was an example and not part of the final code.

  • Mk

    That one had me to. I found what looks like the solution here;
    http://www.deluxeblogtips.com/2010/05/add-custom-column.html

    seem to be “manage_edit-POSTTYPE_columns”

  • http://www.facebook.com/christopherdosin Christopher Dosin

    awesome !
    thanks for this kick ass tutorial mate!

  • http://www.cashgrey.com Shreedhar

    Thanks, its really a headstart for my new work

  • http://www.facebook.com/tomkenkel Tom Kenkel

    Add an underscore before the values to hide them from custom field values.

  • http://www.facebook.com/anton.savkin Anton Savkin

    Thank you
    The best I Have Found

  • http://www.facebook.com/people/James-Gw-Turpin/1821928076 James Gw Turpin

    Great walk-through!

    I am using the the_meta() function to display the custom fields on the page. but issue is that the custom field keys are showing up like custom_key_name instead of Custom Key Name.

    Is there anything that I can do to fix this?

    My code:

    Outputting:

    custom_field_name: Value I Typed In

  • Guest

    What do you exactly mean? I believe that’s a normal behavior as meta boxes = custom fields? :)

  • http://twitter.com/alexduncan Alex Duncan

    Be careful when creating a custom taxonomy. For safety you should not include capitals in the taxonomy slug. The recent update to WP 3.1 shows errors when you try to edit taxonomies in the back end if their slug contains a capital letter. This is predictably an incredibly difficult problem to undo.

  • Kaizer1v

    How do you display these custom post types that you just created?

  • Devinderkumar

    will you please tell me how i apply validation on the field of custom post type, i make that one and now facing problem of applying validation on title, description and custom fields.

  • http://scottelkin.com/ Scott Elkin

    Do you know of a good solution to show a list of custom post type / category?

    A common way to view a posts withing a category would be /category/category-name/.

    And now with WordPress 3.1, you can list all custom types post by going to /custom-post-type-name/.

    But how do I view /custom-post-type-name/category-name/?

    The only way I know of is to create a page and template, which is a bit hacky.

  • http://www.zenofwordpress.com Greg Turner

    Thank you very much for this. It helped me really get the hang of what post types are all about. I have an application where I think using custom post types will work nicely. In this application I will want to add a custom data field for a date. Either one field, or three for month,day, and year. I am wondering in my loop will I be able to do an orderby my custom data type. Anyone know the answer? Thanks again.

  • http://scottelkin.com/ Scott Elkin

    If you do a custom field, I believe it is stored as text. So you will need to make sure that you store the date so that it can be sorted like YEARMONTHDAY (20110317).

    Then read this: http://wordpress.org/support/topic/how-do-i-sort-posts-by-a-custom-field

  • http://www.zenofwordpress.com Greg Turner

    Yes, all that is really obvious. My question has to do with ordering a list by a custom data field within a custom post type, not a custom field. Although I would expect on the back end the implementation is the same.

  • Henri Idstrom

    Very nice post. Just one thing

    register_taxonomy(“Skills” TO >
    register_taxonomy(“skills”

    WP3 Right?

  • Henri

    What about a Company listing system. if i have about 1000-3000 companies and everyone have about 30 metaboxes. Is metaboxes the right way to store data in WP or should i make a own table to the company listing.

    The postmeta table seems to be hard to maintane. I think with that much data it should have own table? Is there any way in WP to maintaine a DB table like custom posts meta information?

  • Jamesssy

    Great article. Rounded up every thing perfectly. Only problem is I want to redo previous sites using this!

  • http://twitter.com/Entherman Nauris Pukis

    Thank you so much for this awesome article. I was googling about the Custom post types and stumbled on this. Will have much more stuff to dig into :)

  • http://awesome-media.net/portfolio/ Timo Burmeister

    Great tutorial! I’ve read a lot about custom posts, but yours really works! ;)

    thanks!

  • Fox Hats

    Thank you, thank you, thank you, thank you, thank you, thank you, thank you, thank you, thank you,

  • Damon

    @Alex, thanks as this helped me fix why it wasn’t working for me, and I still have a few pieces of hair left :-/ Make sure you register taxonomy as: register_taxonomy("skills", array("portfolio"), array("hierarchical" => true, "label" => "Skills", "singular_label" => "Skill", "rewrite" => true));

  • http://twitter.com/blogrstemplates Bloggers Templates

    Whoa…Nice Tutorial.

  • http://twitter.com/saadibrahim Saad Ibrahim

    just remove custom fields from supports parameter when creating a new post type

  • http://twitter.com/ldexterldesign Lewis Litanzios

    No compatibility with standard widgets (i.e. ‘Categories’/'Recent Posts’ etc.)

    Anyone know where to fork these scripts to plug that hole?

    Cheers,

  • http://twitter.com/ldexterldesign Lewis Litanzios

    Would be helpful addition if a ‘Step 5′ covered querying for these custom posts, so we could output them in our page templates.

    Cheers,

  • Anonymous

    very good point, you get an error otherwise that says “Cheatin’ huh”

  • http://twitter.com/bankreviewBR BankReview.com.br

    Brilliant. Much more detailed than the official documentation on the CODEX. Followed this through while making modifications to get to my specific entity I needed and work out superbly.

  • Saintdo

    Thanks so much. You helped me :D

  • http://twitter.com/todayinweb Today in Web

    One way to add the year above the post for example. This will make sure the field is not empty and will post the contents if it is not.

    0){
    {
    echo ‘Completed:’;
    $custom["year_completed"][0];
    }
    the_content(); ?>

  • beth

    I need help getting the data to show, cannot figure out how to. I need to pull the post links to populate a list and the list should then link me to each single page per post.

    I can’t get it to work… but I have no clue how either. Please help email me at info at cddaruba.com thanks!

  • Sarah

    Hopefully someone is still reading this… I’ve used this fairly standard method above to make custom post types and everything seemed to be working fine, except… I just realized when I try to edit a post scheduled for the future it doesn’t retain the custom field edits. Basically I can input data but once it’s in I can’t edit it. A bit of a problem. Any ideas??

Badges for Treehouse

Treehouse

Learn iOS, Rails, CSS3, jQuery, Node.js, HTML5, UX and more in less than 8 minutes per day. New videos added regularly. Sign up today and get a free Web Design Toolkit.

Ads Via The Deck

Think Vitamin Radio
Episode #34: Amazon Fire and Responsive Roundtable

Check out our bi-weekly radio show. Covering the hot topics on the web.

Audio clip: Adobe Flash Player (version 9 or above) is required to play this audio clip. Download the latest version here. You also need to have JavaScript enabled in your browser.

Download Podcast as mp3

Advisory Board

The Think Vitamin Advisory Board in place make sure that you receive the best content possible.