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:
<?php /** * Plugin Name: Book Custom post type * Plugin URI: managewp.com/blog * Description: A plugin to create a custom post type for Books * Version: 1.0 * Author: Your name goes here * Author URI:Your website goes here * License: GPL2 */ add_action( 'init', 'book_init' ); /** * Register a book post type. * */ function codex_book_init() { $labels = array( 'name' => __( 'Books', 'post type general name', 'your-plugin-textdomain' ), 'singular_name' => __( 'Book', 'post type singular name', 'your-plugin-textdomain' ) ); register_post_type( 'book', $args ); }
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:
<?php /** * Plugin Name: Book Custom post type * Plugin URI: managewp.com/blog * Description: A plugin to create a custom post type for Books * Version: 1.0 * Author: Your name goes here * Author URI:Your website goes here * License: GPL2 */
After that, we get down to actually starting to build the plugin:
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.
function book_init() { $labels = array( ‘name' => __( 'Books', 'post type general name', 'your-plugin-textdomain' ), 'singular_name=> __( 'Book', 'post type singular name', 'your-plugin-textdomain' ), 'menu_name' => __( 'Books', 'admin menu', 'your-plugin-textdomain' ), 'name_admin_bar'=> __( 'Book', 'add new on admin bar', 'your-plugin-textdomain' ), 'add_new' => __( 'Add New', 'book', 'your-plugin-textdomain' ), 'add_new_item'=> __( 'Add New Book', 'your-plugin-textdomain' ), 'new_item' => __( 'New Book', 'your-plugin-textdomain' ), 'edit_item' => __( 'Edit Book', 'your-plugin-textdomain' ), 'view_item' => __( 'View Book', 'your-plugin-textdomain' ), 'all_items' => __( 'All Books', 'your-plugin-textdomain' ), 'search_items'=> __( 'Search Books', 'your-plugin-textdomain' ), 'parent_item_colon' => __( 'Parent Books:', 'your-plugin-textdomain' ), 'not_found' => __( 'No books found.', 'your-plugin-textdomain' ), 'not_found_in_trash' => __( 'No books found in Trash.', 'your-plugin-textdomain' ) );
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
$args = array( 'labels' => $labels, 'public' => true, 'publicly_queryable' => true, 'show_ui' => true, 'show_in_menu' => true, 'query_var' => true, 'rewrite' => array( 'slug' => 'book' ), 'capability_type' => 'post', 'has_archive' => true, 'Hierarchical’ => false, 'menu_position' => null, 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ) );
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.
Augusto Carmo
Where is the the part II?
cytoolove
We’d love to chat!
João Lindoso
Muito bom o seu Post. Bem objetivo! quando virá a segunda parte?
Very good your Post. Simple and straightforward. When will the second part?
Nelson
Great Post, Thanks ??
Tom
Is there ever going to be part 2?
Sreejith A
Hello, most importantly thank you for posting on this point with awesome clarification. I Have seeking long to locate a decent article and at long last I got by answer with clear clarification .Thanks a considerable measure
Admin@CydiaGuide
Excellent! I was Struggling with PLUGINS for Custom Shortcodes
Mr Brother
Can This Work For Blogger?
Ekansh Saxena
Could you please post the next parts of this series.
Ekansh Saxena
Hi,
well explained. I tried searching for the second part of this but was not successful. Please post the second part of this series and link it here also.
Dean
Is there a way you can show me this all in one complete block of code instead of broken into chunks?
ميسرة
Thanks
Anna
Amazing tut!!!!!
Nelson
Excellent tut.When Will part 2 of this come out? I am eagerly waiting for it 🙂
zamican
Very interesting article in content and style (As an avid reader of your regular weekly notifications, I look forward to receiving them)
Most of it went over my head! Perhaps you could recommend a plug-in for this purpose? I am sure it would be well received by non coders like me.
mbox
Great tut: but you did leave out ‘menu_icon’ argument, which takes an image URL as the value. Then that icon displays next the the CPT name in the dashboard.
Buka Info
great way but I have not quite understood about the correct php program but I will try to add a tutorial on the book page wordpress
Rezan Ferdous
Just awesome. Thanks for the tips.
Vladimir
I could not resist refrain from commenting. Well Exceptionally well written!