How To Create Custom Post Types For your WordPress Website (Part 1)

Custom post types have allowed a wide variety of content to be displayed in a WordPress site since version 2.9 was released.

Before that, you had the ability to create static pages and posts, which in itself was a huge leap at the time. But with the addition of the register_post_type() function being added, along with a few other helpful things, this really allowed WordPress to explode and start taking the market dominance it now has. In this article we will begin creating a custom post type called ‘Books’ which by the end of the series will be a fully functioning book review post type.

A custom post type is nothing more than a regular post with a different post type value attached to it. The post type for a regular one is post, for pages it’s simply page, and so on. With custom post types you can create posts for books, movies, reviews, recipes, etc.

Custom post types offer a lot of flexibility for where the post type should be placed in the menu, if it is searchable, what user level has access to it, should it be hierarchical, and so on.

Making Custom Post Types Work

In order to effectively create and use custom post types, you’ll need to be familiar with the following:

  • Creating custom post types
  • Creating custom taxonomies
  • Creating custom meta boxes

So let’s get started with creating that custom post type.

Creating Custom Post Types

The first thing we need to do is actually create the custom post type. You have a couple of options here, the first being to add the code to the functions.php file for your theme. While this works just fine, I prefer to create a plugin for my custom post types.

So for this exercise we are going to create a plugin for a custom post type called ‘Books’. Of course, we first have to create a new folder in wp-content/plugins. I called mine ‘Book Custom Post Type’ but you can name it what you like. I then created a file called booksposttype.php within the folder and added the following code:

  1. <?php
  2. /**
  3. * Plugin Name: Book Custom post type
  4. * Plugin URI:
  5. * Description: A plugin to create a custom post type for Books
  6. * Version:  1.0
  7. * Author: Your name goes here
  8. * Author URI:Your website goes here
  9. * License:  GPL2
  10. */
  11. add_action( ‘init’, ‘book_init’ );
  12. /**
  13. * Register a book post type.
  14. *
  15. */
  16. function codex_book_init() {
  17. $labels = array(
  18. ‘name’               => __( ‘Books’, ‘post type general name’, ‘your-plugin-textdomain’ ),
  19. ‘singular_name’      => __( ‘Book’, ‘post type singular name’, ‘your-plugin-textdomain’ )
  20. );
  21. register_post_type( ‘book’, $args );
  22. }

So lets back up a bit and explain what we have done here.

The opening section is simply just declaring that we are building a plugin. While the code is comments out, WordPress looks for it and knows that it is to handle it as a plugin, rather than a theme or anything else.

Declaring the plugin:

  1. <?php
  2. /**
  3. * Plugin Name: Book Custom post type
  4. * Plugin URI:
  5. * Description: A plugin to create a custom post type for Books
  6. * Version:  1.0
  7. * Author: Your name goes here
  8. * Author URI:Your website goes here
  9. * License:  GPL2
  10. */

After that, we get down to actually starting to build the plugin:

  1. add_action( ‘init’, ‘book_init’ );

The first part simply tells WordPress that you are going to hook a function to a specific action. The ‘init’ call runs after WordPress has finished loading but before any headers are sent. And ‘book_init’ is simply what we called our function.

The next part describes what we want the custom post type to do. At this stage we are creating the function for the Book Custom post type and simply giving it a couple of labels: one singular and one plural. The last thing we did was register the custom post type register_post_type( ‘book’, $args );

If you save this and then go to your WordPress Dashboard and head over to the plugins section, you will see a new plugin called ‘Book Custom Post type’ (or whatever you named your plugin). The sad thing is if you activate the plugin nothing happens, so let’s go add some more to this.

So we are going to introduce a lot more code to the labels area of our custom post type. Just add the code beginning with “menu_name” to what you already have and we’ll work through the different items right below.

  1. function book_init() {
  2. $labels = array(
  3. ‘name‘ => __( ‘Books‘, ‘post type general name‘, ‘yourplugintextdomain‘ ),
  4. singular_name=> __( ‘Book’, ‘post type singular name’, ‘your-plugin-textdomain’ ),
  5. ‘menu_name’ => __( ‘Books’, ‘admin menu’, ‘your-plugin-textdomain’ ),
  6. ‘name_admin_bar’=> __( ‘Book’, ‘add new on admin bar’, ‘your-plugin-textdomain’ ),
  7. ‘add_new’   => __( ‘Add New’, ‘book’, ‘your-plugin-textdomain’ ),
  8. ‘add_new_item’=> __( ‘Add New Book’, ‘your-plugin-textdomain’ ),
  9. ‘new_item’    => __( ‘New Book’, ‘your-plugin-textdomain’ ),
  10. ‘edit_item’     => __( ‘Edit Book’, ‘your-plugin-textdomain’ ),
  11. ‘view_item’   => __( ‘View Book’, ‘your-plugin-textdomain’ ),
  12. ‘all_items’     => __( ‘All Books’, ‘your-plugin-textdomain’ ),
  13. ‘search_items’=> __( ‘Search Books’, ‘your-plugin-textdomain’ ),
  14. ‘parent_item_colon’ => __( ‘Parent Books:’, ‘your-plugin-textdomain’ ),
  15. ‘not_found’  => __( ‘No books found.’, ‘your-plugin-textdomain’ ),
  16. ‘not_found_in_trash’ => __( ‘No books found in Trash.’, ‘your-plugin-textdomain’ )
  17. );

So we have looked at ‘name’ and ‘singular_name’ but there is a piece at the end that we should cover quickly and that’s the ‘your-plugin-textdomain’ line, which appears on each label. Its purpose is to load the plugins translated or localized strings.

And here is a quick run down of what each of those labels does for our custom post type:

  • ‘name’ general name for the post type, typically plural.
  • ‘singular_name’ you guessed it. The name for a single object of this post type.
  • ‘menu_name’ the name that shows on the menu. If not declared it defaults to the value of ‘name’.
  • ‘name_admin_bar’ the name given for the ‘Add New’ dropdown on the admin bar.
  • ‘add-new’ the add new text.
  • ‘add_new_item’ the add new item text. The default is Add New Post or Add New Page.
  • ‘new_item’ the new item text. The default is “New Post” or “New Page”.
  • ‘edit_item’ the edit item text. This is found in the UI and is used as the main header on the post’s editing panel/ Default id ‘ Edit Post’ or Edit Page’.
  • ‘view item’ the view item y=text. Default is View Post/View Page.
  • ‘search_item’ the search items text. Default is Search Posts/Search Pages
  • ‘parent_item_colon’ the parent text. This string is used only in hierarchical post types. Default is ‘Parent Page’.
  • ‘not-found’ the not found text/default is No posts found/No pages found
  • ‘not_found_in _trash’ the not found in trash text/ Default is No posts found in trash/No pages in trash.

So we have put all the labels we want into the custom post type and now we have to add the arguments that contain the variables for our custom post type.

These go right below the $labels array and before the ‘register_post_type’ line

  1. $args = array(
  2.         ‘labels’             => $labels,
  3.         ‘public’             => true,
  4.         ‘publicly_queryable’ => true,
  5.         ‘show_ui’            => true,
  6.         ‘show_in_menu’       => true,
  7.         ‘query_var’          => true,
  8.         ‘rewrite’            => array( ‘slug’ => ‘book’ ),
  9.         ‘capability_type’    => ‘post’,
  10.         ‘has_archive’        => true,
  11.         ‘Hierarchical’       => false,
  12.         ‘menu_position‘      => null,
  13.         ‘supports‘           => array( ‘title‘, ‘editor‘, ‘author‘, ‘thumbnail‘, ‘excerpt‘, ‘comments‘ )
  14.     );

So lets do a quick run down on what we have included in our variables:

  • ‘labels’ ensures all of our labels are included.
  • ‘public’ determines whether a post type is intended to be used publicly either through the admin interface or by front end users. The default is ‘false’
  • ‘publicly_queryable’ determines whether queries can be performed on the front end as part of parse_request().
  • ‘show_ui’ determines whether to generate a default UI for managing this post type in the admin
  • ‘query_var’ this sets the query_var key for the post type. The default here is ‘true’.
  • ‘rewrite’ triggers the handling of rewrites for this post type.
  • ‘capability_type’ the string used to build the read, edit and delete capabilities. This is also used as a base to construct capabilities unless they are set out explicitly in the ‘capabilities’ parameter. Can be passed as an array.
  • ‘has_archive’ enables archives for the custom post type
  •  ’Hierarchical’ whether or not the post type is hierarchical (e.g. pages)
  • ‘menu_position’ the position in the menu order the post type should appear.
  • ‘supports’ this is an alias for add_post-type-support() these can be passed in an array and the defaults are title and editor

Okay, so once you’ve added all this code and saved your plugin, go back to your dashboard, refresh the screen and you should now see your custom post type available to you in the dashboard menu.

The first thing you should notice is the addition of the Books menu item in the sidebar, and when you click on ‘Add New’ you will see an editor with the title ‘Add New Book’.

Congratulations! You have created your first custom post type.

Next week we will expand on this and add a custom taxonomies and some custom post meta boxes to make this workable and give it some polish and flair.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s