WordPress is a platform which lets you create whatever you want from it. Creating custom post type is one of the main reason behind WordPress’s wide range of customization. In this tutorial I’ll discuss everything you need to know about custom post type of WordPress to develop any kind website.
Before getting into custom post type, let’s first discuss about post type. By codex reference, a post is a single item of a type of content and this type of content is called post type. There are several kinds of post types available in WordPress.
- Post (Used for blog articles)
- Page (Used for pages like about, services, contact etc.)
- Attachment (Used for files uploaded to website like images, pdf, zip files etc.)
- Revision (stores every update made on posts or pages)
All this post type stores on wp_posts table on database of WordPress and differentiated by post_type column.
What is Custom Post Type (CPT) in WordPress?
As the name suggests it is a way to define our own post types to WordPress. By doing this we can extend WP to limitless usage. Examples of CPT can be portfolio, books, movies, reviews etc.
To create a CPT in WordPress we have to write this code below in a plugin. To know how to create plugin, see my plugin development tutorial.
function register_my_cpt_post_type() { $args = array( 'labels' => array( 'name' => __( 'Portfolio', 'mt-portfolio' ), 'singular_name' => __( 'Portfolio', 'mt-portfolio' ), 'menu_name' => __( 'Portfolio', 'mt-portfolio' ), 'name_admin_bar' => __( 'Portfolio', 'mt-portfolio' ), 'add_new' => __( 'Add New', 'mt-portfolio' ), 'add_new_item' => __( 'Add New Portfolio', 'mt-portfolio' ), 'new_item' => __( 'New Portfolio', 'mt-portfolio' ), 'edit_item' => __( 'Edit Portfolio', 'mt-portfolio' ), 'view_item' => __( 'View Portfolio', 'mt-portfolio' ), 'all_items' => __( 'All Portfolio', 'mt-portfolio' ), 'search_items' => __( 'Search Portfolio', 'mt-portfolio' ), 'parent_item_colon' => __( 'Parent Portfolio:', 'mt-portfolio' ), 'not_found' => __( 'No portfolios found.', 'mt-portfolio' ), 'not_found_in_trash' => __( 'No portfolios found in Trash.', 'mt-portfolio' ) ), 'query_var' => 'portfolio', 'rewrite' => array( 'slug' => 'portfolio', 'with_front' => false ), 'public' => true, 'publicly_queryable' => true, 'show_ui' => true, 'has_archive' => true, 'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' ) ); flush_rewrite_rules(); register_post_type('portfolio', $args); } add_action( 'init', 'register_my_cpt_post_type' );
Here I have registered a CPT called portfolio using register_post_type() function, which is a WP function for registering CPT. Then with init action hook we included our function register_my_cpt_port_type to WP. To know about hooks in details see my tutorial on WP hooks and filters.
If you want to create CPT, which doesn’t need permalink for its posts, then you can make this change in code while registering the CPT. This kind of CPT is required for testimonials or reviews, you need to add reviews posts to display it on your site but it is not necessary to have permalink for single reviews.
function register_my_cpt_post_type() { $args = array( 'labels' => array( 'name' => __( 'Reviews', 'review' ), 'singular_name' => __( 'Review', 'review' ), 'menu_name' => __( 'Reviews', 'review' ), 'name_admin_bar' => __( 'Reviews', 'review' ), 'add_new' => __( 'Add New', 'review' ), 'add_new_item' => __( 'Add New Review', 'review' ), 'new_item' => __( 'New Review', 'review' ), 'edit_item' => __( 'Edit Review', 'review' ), 'view_item' => __( 'View Review', 'review' ), 'all_items' => __( 'All Review', 'review' ), 'search_items' => __( 'Search Review', 'review' ), 'parent_item_colon' => __( 'Parent Review:', 'review' ), 'not_found' => __( 'No Reviews found.', 'review' ), 'not_found_in_trash' => __( 'No Reviews found in Trash.', 'review' ) ), 'public' => false, // If you don't want it to make public, make it false 'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' ) ); flush_rewrite_rules(); register_post_type('review', $args); } add_action( 'init', 'register_my_cpt_post_type' );
Just make argument public as false and single posts of the CPT will not have any permalink.
WordPress has multiple user roles by default and there will be many cases where you want to give CPT managing capability to certain users like administrator and editor. In that case you can add few extra arguments while registering CPT.
function register_my_cpt_post_type() { $args = array( 'labels' => array( 'name' => __( 'Portfolio', 'mt-portfolio' ), 'singular_name' => __( 'Portfolio', 'mt-portfolio' ), 'menu_name' => __( 'Portfolio', 'mt-portfolio' ), 'name_admin_bar' => __( 'Portfolio', 'mt-portfolio' ), 'add_new' => __( 'Add New', 'mt-portfolio' ), 'add_new_item' => __( 'Add New Portfolio', 'mt-portfolio' ), 'new_item' => __( 'New Portfolio', 'mt-portfolio' ), 'edit_item' => __( 'Edit Portfolio', 'mt-portfolio' ), 'view_item' => __( 'View Portfolio', 'mt-portfolio' ), 'all_items' => __( 'All Portfolio', 'mt-portfolio' ), 'search_items' => __( 'Search Portfolio', 'mt-portfolio' ), 'parent_item_colon' => __( 'Parent Portfolio:', 'mt-portfolio' ), 'not_found' => __( 'No portfolios found.', 'mt-portfolio' ), 'not_found_in_trash' => __( 'No portfolios found in Trash.', 'mt-portfolio' ) ), 'public' => true, 'publicly_queryable' => true, 'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' ), 'capability_type' => 'portfolio', 'capabilities' => array( 'publish_posts' => 'publish_portfolios', 'edit_posts' => 'edit_portfolios', 'edit_others_posts' => 'edit_others_portfolios', 'delete_posts' => 'delete_portfolios', 'delete_others_posts' => 'delete_others_portfolios', 'read_private_posts' => 'read_private_portfolios', 'edit_post' => 'edit_portfolio', 'delete_post' => 'delete_portfolio', 'read_post' => 'read_portfolio', ) ); flush_rewrite_rules(); register_post_type('portfolio', $args); } add_action( 'init', 'register_my_cpt_post_type' );
Here I have added capabilities with the post type and we can apply this capabilities to our users based upon their role.
So these are few different cases CPT and how to register them. If you want to know about any other different cases for CPT, which I haven’t mentioned here, then let me know by commenting down below.
Happy coding.