WordPress 3 custom post types

Update

For a more detailed look at building custom post types, see my recent article WordPress Custom Post Type Boilerplate: part 1.

How to create a portfolio page with a custom post type & page template

Wordpress 3 custom post type

WordPress 3 has a handy new feature for creating custom post types that can be managed via their own main menu item. A website such as this one is an ideal candidate, as the 'Posts' menu is used for blog posts and the 'Pages' menu is used for everything else, so now we can create a home for everything that appears on the 'Portfolio' page and manage this very easily in the back end. It is possible to define any custom post type that you want, for example 'Video', 'Recipes', 'Products', and each will have it's own home in the admin menu.

Here is how-to guide I have put together by compiling tips from other articles into a complete process for my own scenario.

1. Define custom post type

Firstly, you need to add the relevant code to your functions.php file to define the custom post type and its parameters.

add_action('init', 'post_type_portfolio');

function post_type_portfolio() {
	register_post_type( 'Portfolio', array(
		'label' => __('Portfolio'),
		'public' => true,
		'show_ui' => true,
		'_builtin' => false, // It's a custom post type, not built in
		'_edit_link' => 'post.php?post=%d',
		'capability_type' => 'post',
		'hierarchical' => false,
		'rewrite' => array("slug" => "portfolio"), // Permalinks
		'query_var' => "portfolio",
		'menu_position' => 20,
		'supports' => array('title', 'excerpt', 'editor', 'thumbnail',),
	));
        // add the following function if you are getting 
        // a 'Page not found' error from your permalink
		flush_rewrite_rules( false );
}
  • add_action tells your theme to run your post_type_portfolio function from the get-go ('init').
  • label defines how the post type will appear in your menu
  • menu_postition defines where the menu will appear. 5 for under 'Posts', 10 for under 'Media', 20 for under 'Pages'. If this parameter is left out it will default to under 'Comments'
  • supports defines what options boxes will appear in the editor section. 'thumbnail' has been included as per my discussion below.
  • flush_rewrite_rules will fix the 404 error 'page not found' when using /%slug%/%post_name%/ permalink format.

For more information about the rest of the above parameters, see Elliot Condon's custom post type article; Kovshenin's explanation of permalinks with custom post type; and for a complete run-down, the WordPress Codex Function Reference .

Special thanks to Nooshu for the flush_rewrite_rules fix of the permalinks giving a 'Page not found' 404 error.

2. Define custom taxonomy

If necessary, you can include some custom taxonomy (nerdo word meaning data classification) for the post type. This is the same as categories for posts, however you can use whatever names you like, such as 'Project Type'.

I have added the following code just inside the closing "}" of the above function:

register_taxonomy( "Project Type", array("Portfolio"), array(
		"hierarchical" => true,
		"label" => "Project Types",
		"singular_label" => "Project Type",
		"rewrite" => true
));

3. Create a template page

Now that you can create your custom posts, you need to display them in the appropriate place on your site. I have created a template page using the existing WordPress functionality and assigned my Portfolio page to this template. For those not familiar with this, simply duplicate the page.php file and modify the get_header() code like so:

<?php
**
Template name: Portfolio
**/
get_header(); ?>

4. Add loop to template page to call custom posts

In my scenario, I want the Portfolio page to work in the same way as a posts page. This requires adding some code before the loop to call the custom posts.

<?php
  global $post;
  $myposts = get_posts(array(
    'post_type' => 'portfolio',
    'numberposts' => '999',
    'orderby' => 'menu_order',
    'order' => 'ASC'
  ));
  foreach($myposts as $post):
?>

<?php setup_postdata($post) ?>
  <h2><a
    title="<?php the_title(); ?>"
    href="<?php the_permalink() ?>"
    rel="bookmark"><?php the_title(); ?>
  </a></h2>

<?php the_post_thumbnail(); ?>
<?php the_excerpt('Read more...'); ?>

<?php endforeach; wp_reset_query(); ?>

Thanks again to Elliot Condon's article for this code.

5. Enable post thumbnails

wordpress post thumbnail

To make use of another new feature (as of version 2.9) I have added a post thumbnail to the portfolio post type. This feature needs to be enabled by adding the following code to your functions.php file:

add_theme_support( 'post-thumbnails' );
set_post_thumbnail_size( 150, 150, true ); // 150x150 pixels, hard crop mode

As mentioned above, the supports parameter of the register_post_type array has 'thumbnail' included, so the editor will now show the 'Featured Image' option box.

wordpress featured image

For more information on using featured images see Mark Jaquith's post thumbnail images article or the WordPress Codex reference.

Other articles I came across on this topic are:

9 Responses to “WordPress 3 custom post types”

  1. Patrick says:

    How can you add pagination to the new custom loop? When I click on a portfolio entry and it opens to the single post page, I want to add a “go to next post” link, but it will not work.

    Anybody help me??

    • Tim says:

      Hi Patrick,

      I added next post and previous post links on a recent project – see here. This is simply done by using the next_post() and previous_post() functions.

      For this particular project I used the functions in the following context:

      <div class="posts-nav-links">
      <li class="previous"><?php previous_post(‘%’,’&laquo; Previous’, ‘no’); ?></li> |
      <li class="back"><a href="/portfolio">Back to Portfolio</a></li> |
      <li class="next"><?php next_post(‘%’,’Next &raquo;’, ‘no’); ?></li>
      </div>

      Note that these tags are deprecated, and should be replaced with next_post_link() and previous_post_link(), respectively.

  2. Patrick says:

    Thanks for getting back to me! For some reason, when I add that to my template file, it just gives me a blank screen.

    Take a look here:
    <!–

    ‘portfolio’,
    ‘numberposts’ => ‘999’,
    ‘orderby’ => ‘id’,
    ‘order’ => ‘ASC’,
    ‘posts_per_page’=> ‘3’,
    ‘paged’=> $paged

    ));
    foreach($myposts as $post):
    ?>

    <a
    title="”
    href=””
    rel=”bookmark”>

    <a href="”>

    –>

  3. Patrick says:

    Sorry, that only posted some of the content. Anyways, do you know what might be wrong?

    I have a support forum going on this:

    http://wordpress.org/support/topic/pagination-and-a-custom-post-loop?replies=9#post-1970825

  4. Tim says:

    Hi Patrick, I have posted a reply to your WordPress forum post here: http://wordpress.org/support/topic/pagination-and-a-custom-post-loop

    Cheers,

    Tim.

  5. QLStudio says:

    Hey Tim – thanks for the link to the flush rule.

    I’m not sure this has made much difference, the most important things I added to get my permalinks working were:

    in “register_post_type”

    ‘rewrite’ => array( “slug” => “publication” ),
    ‘_builtin’ => false,

    then in each of my “register_taxonomy”

    ‘rewrite’ => array( ‘slug’ => ‘publication/label’ )

    adding this to my custom taxonomies got the permalinks working.

    I use “/%post_id%/%category%/%postname%/” as the setting

    now – what I need is a yearly based archive for my CPT – I’ve tried both the recommended CPT archive plugins, but out of the box, they don’t seem to work.

    I thought about and read about the idea that having a page with the same slug as your custom post type ( in singular or plural form ) might cause a conflict with the rewrites – but I can’t say for sure that’s the problem.

    Sorry this is a bit rambling – this has been annoying me for days – I can post more complete code and a link to an online example if you can’t quite follow the problem.

    Cheers for any help you can offer.

    QL

    • Tim says:

      Hi QL,

      I believe what you are trying to do requires some more extensive development than what the custom post types function offers. I tried to customise CPT permalinks for a job a few months back and I couldn’t get it working the way I wanted.

      I bought a copy of WordPress Plugin Development last week and I had a quick look in there for some answers for you. There is an entire chapter on the WordPress Rewrite API, so perhaps you could start by looking in the Codex.

      I can’t offer any specific advice as I have not successfully done something like what you are trying to do, but hopefully that will point you in the right direction.

      Also, I have written a CPT base plugin file for myself with a bunch of related functions, which I have uploaded as a txt version here. Although this does not cover rewrite rules, you may find it useful. Just rename the extension to .php or copy the code into a fresh PHP file if you want to take a look. I plan to write up a post about it but haven’t yet had time, so please excuse any comments in the file which may not make sense.

      Tim.

  6. Henry says:

    Hello, I’m in the process of following this quick tutorial and for the first part when i add the first line of code to my functions.php i get an unexpected syntax error on line 38 of my. which is this

    ));
    // permalink 404 error
    // add the following function if you are getting
    // a ‘Page not found’ error from your permalink
    flush_rewrite_rules( false );

    What am i doing wrong here?

    • Tim says:

      Sorry Henry, my bad. There was some HTML inside that snippet that shouldn’t have been there. I recently updated how I handle snippets and this was apparently a side effect. I have updated the relevant snippet in this post now. I also cover a bunch of custom post type code in this article.

      Also, keep in mind this article is quite old, so some stuff may bit a bit out of date. Another really good article is this one by Justin Tadlock. It is also a few years old, but he is a reputable source.