Create An Image Slide Plugin Part 3: Create A Custom Post Type

Create An Image Slide Plugin Part 3: Create A Custom Post Type

In this post from the series of tutorials on creating a WordPress plugin for displaying image slides we’ll learn how to create a custom post type which will house the functionality, content and metadata information of our image slides.

In the previous post we set things up using the WordPress Plugin Boilerplate which gave us a solid start with a lot of best practice and standards compliant code already available to us. We also looked at some of the important files and folders that make up our plugin.

In this post we’ll start creating the image slide using a piece of functionality that WordPress offers, called custom post types, often referred to as custom content types. Before we get to that let’s dig into more details about this built-in WordPress functionality.

What Is A Custom Post Type?

In WordPress, a ‘post’ can mean two things:

  1. an entry or piece of content that a user creates or WordPress generates and that has a post / content type. A blog post or page are some common entries that users create
  2. a piece of content that has a type of 'post'

WordPress has several post or content types readily available to be used for your content. These are often called the default post types:

  • Post (Post Type: 'post')
  • Page (Post Type: 'page')
  • Attachment (Post Type: 'attachment')
  • Revision (Post Type: 'revision')
  • Navigation Menu (Post Type: 'nav_menu_item')
  • Custom CSS (Post Type: 'custom_css')
  • Changesets (Post Type: 'customize_changeset')

As the name suggests, a custom content type is a post type with content and functionality defined by users.

With custom content types we have much more control over the information that is provided and how it is displayed. This functionality is of huge importance to the WordPress core as well as themes and plugins.

Custom Content Type Prerequisites

The action of creating a custom content type is called ‘registering’. The registering consists of some information we must provide in order for WordPress to know and handle the content type.

Looking through the official documentation on registering a custom post type, we can create a list of things to do in order to create our custom content type:

  • We need to use the register_post_type() built-in function to tell WordPress about the new content type.
  • We need to use the init hook as the the moment in the WordPress loading sequence that the new content type should become available.
  • We need to come up with a name for our custom content type.

Aside from what we got from looking through the documentation we also need to establish a place in our plugin’s files where we’ll put the actual code for creating the content type.

We’ll start by creating a new class file that will house the bulk of our custom post type functionality.

So, create a new file called /admin/class-monospace-slides-cpt.php. As you can see it resides in the /admin folder.

The most important piece of information about a custom content is its ‘type’ or the ‘slug’ that the content goes by internally in WordPress core, themes and plugins.

The type of our custom content will be mnsp_slide.

Register A Custom Content Type

If you want to follow along I’ve set up a GitHub repository where you’ll find the code from this series. The finished code for this post is in the part_3 branch. If you want to follow along please download the part_2 branch.

Now we have some solid knowledge about custom content types. Let’s get on with actually creating our slide custom content type in the admin of WordPress. As we’ve established before, this means registering the content type.

Let’s do this in stages.

Open the newly created file and add the following code:

 * The admin-specific functionality for creating a custom post type.
 * @link
 * @since      1.0.0
 * @package    Monospace_Slides
 * @subpackage Monospace_Slides/admin

 * The admin-specific functionality for creating a custom post type.
 * Defines all the functionality related to creating and managing a custom post type.
 * @package    Monospace_Slides
 * @subpackage Monospace_Slides/admin
 * @author     Mike In Monospace <>
class Monospace_Slides_CPT {

	 * Creates a new custom post type
	 * @since 1.0.0
	 * @access public
	 * @uses register_post_type()
	public static function new_cpt_slide() {

		$cap_type = 'post';
		$cpt_name = 'mnsp_slide';

		$labels = array(
			'name'                  => esc_html_x( 'Slides', 'Post Type General Name', 'monospace-slides' ),
			'singular_name'         => esc_html_x( 'Slide', 'Post Type Singular Name', 'monospace-slides' ),
			'menu_name'             => esc_html__( 'Slides', 'monospace-slides' ),
			'name_admin_bar'        => esc_html__( 'Slide', 'monospace-slides' ),
			'archives'              => esc_html__( 'Slide Archives', 'monospace-slides' ),
			'attributes'            => esc_html__( 'Slide Attributes', 'monospace-slides' ),
			'parent_item_colon'     => esc_html__( 'Parent Slide:', 'monospace-slides' ),
			'all_items'             => esc_html__( 'All Slides', 'monospace-slides' ),
			'add_new_item'          => esc_html__( 'Add New Slide', 'monospace-slides' ),
			'add_new'               => esc_html__( 'Add New', 'monospace-slides' ),
			'new_item'              => esc_html__( 'New Slide', 'monospace-slides' ),
			'edit_item'             => esc_html__( 'Edit Slide', 'monospace-slides' ),
			'update_item'           => esc_html__( 'Update Slide', 'monospace-slides' ),
			'view_item'             => esc_html__( 'View Slide', 'monospace-slides' ),
			'view_items'            => esc_html__( 'View Slides', 'monospace-slides' ),
			'search_items'          => esc_html__( 'Search Slide', 'monospace-slides' ),
			'not_found'             => esc_html__( 'Not found', 'monospace-slides' ),
			'not_found_in_trash'    => esc_html__( 'Not found in Trash', 'monospace-slides' ),
			'featured_image'        => esc_html__( 'Featured Image', 'monospace-slides' ),
			'set_featured_image'    => esc_html__( 'Set featured image', 'monospace-slides' ),
			'remove_featured_image' => esc_html__( 'Remove featured image', 'monospace-slides' ),
			'use_featured_image'    => esc_html__( 'Use as featured image', 'monospace-slides' ),
			'insert_into_item'      => esc_html__( 'Insert into Slide', 'monospace-slides' ),
			'uploaded_to_this_item' => esc_html__( 'Uploaded to this Slide', 'monospace-slides' ),
			'items_list'            => esc_html__( 'Slides list', 'monospace-slides' ),
			'items_list_navigation' => esc_html__( 'Slides list navigation', 'monospace-slides' ),
			'filter_items_list'     => esc_html__( 'Filter Slides list', 'monospace-slides' ),

		$args = array(
			'label'               => esc_html__( 'Slide', 'monospace-slides' ),
			'description'         => esc_html__( 'A content type for creating image slides', 'monospace-slides' ),
			'labels'              => $labels,
			'menu_icon'           => 'dashicons-welcome-view-site',
			'supports'            => array( 'title', 'thumbnail', 'revisions' ),
			'taxonomies'          => array( 'mnsp_slider' ),
			'public'              => true,
			'show_ui'             => true,
			'show_in_menu'        => true,
			'menu_position'       => 5,
			'show_in_admin_bar'   => true,
			'show_in_nav_menus'   => false,
			'can_export'          => true,
			'has_archive'         => false,
			'hierarchical'        => false,
			'exclude_from_search' => true,
			'show_in_rest'        => true,
			'publicly_queryable'  => false,
			'capability_type'     => $cap_type,

		$args = apply_filters( 'monospace_slides_cpt_options', $args );

		register_post_type( strtolower( $cpt_name ), $args );



As we can see this file declares a class with a method in it, new_cpt_slide() that registers a new custom content type.

Taking a closer look at the method, we can see it declares two array variables containing a set of labels and some arguments. The last line of the method uses the register_post_type() built-in function to tell WordPress about the new content type.

Next, we have to tell WordPress about the new file we created as it doesn’t know it exists yet.

So, open the /includes/class-monospace-slides.php file and in the load_dependencies() method add the following code:

 * The class responsible for the functionality of the custom post type.
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-monospace-slides-cpt.php';

This tells WordPress to load that file as we’ll use functionality from there.

Next, we’ll create a function in this same file that will contain all the hooks for the the new custom content type.

In the __construct method of this file add one line of code add the end:


This tells WordPress to look for a method called define_cpt_hooks() in this file and execute that code.

Add a custom function on the init hook

For the new custom post type to actually get registered we have to tell WordPress to run the new_cpt_slide() method we created earlier in the Monospace_Slides_CPT class.

So, in this same file let’s create the define_cpt_hooks() method we declared above. Add the following code after the define_public_hooks() method:

 * Register all of the hooks related to registering a custom post type
 * as well as customizing the admin columns.
 * @since    1.0.0
 * @access   private
private function define_cpt_hooks() {

	$plugin_cpt = new Monospace_Slides_CPT();

	$this->loader->add_action( 'init', $plugin_cpt, 'new_cpt_slide' );


The code above tells WordPress to look or a function called new_cpt_slide inside the Monospace_Slides_CPT class and run it at the init moment in it’s initialization process.

Now, if we add the new code to our installed plugin and we pop in on the admin side we can see a new menu item for our custom content type, just like in the screenshot below:

Slide Custom Post Type Admin Menu

So, there you have it. An easy way to add our image slides in WordPress.

Next, let’s make sure that WordPress will correctly handle the permalinks and URLs for the posts that will have the new content type. This is done by flushing the rewite rules.

So, open the /includes/class-monospace-slides-activator.php file and in the activate() method add the following code:

 * The class responsible for defining the behavior of the custom post type.
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-monospace-slides-cpt.php';



Customize the WordPress Admin Columns

We’ll now add a column to display the slide’s featured image on the Slides > All Slides admin screen.

Open the /admin/class-monospace-slides-cpt.php file and add these two functions at the end of the class:

 * Creates a new admin column on the custom post type listing screen.
 * @since 1.0.0
 * @param string $columns    The name of the column to add.
 * @access public
public function add_slide_columns( $columns ) {

	$columns['image'] = __( 'Image', 'monospace-slides' );

	return $columns;


 * Displays the featured image of a post in an admin column called 'image'.
 * @since 1.0.0
 * @param string $column     The name of the column.
 * @param int    $post_id    The id of the post.
 * @access public
public function add_slide_columns_content( $column, $post_id ) {

	if ( 'image' === $column ) {
		echo get_the_post_thumbnail( $post_id, array( 80, 80 ) );


Now we’ll add two filters that will use these two functions to add and display the image column. In the /includes/class-monospace-slides.php file add the following code at the end of the define_cpt_hooks() method:

$this->loader->add_filter( 'manage_edit-mnsp_slide_columns', $plugin_cpt, 'add_slide_columns' );
$this->loader->add_filter( 'manage_mnsp_slide_posts_custom_column', $plugin_cpt, 'add_slide_columns_content', 10, 2 );

There, now, whenever you go to see all your slides it will be easier to identify them as each one will show it’s featured image.

Slide Custom Post Type Admin Columns

At The End

This is the first post in which we added some custom code for creating content that WordPress does not support by default.

Let’s recap some key points from this post:

  • We can add custom content by creating a custom post / content type.
  • To add a custom content type we need to tell WordPress about it.
  • We let WordPress know about the new content type by registering it using a custom function and a hook that runs that function at the init moment in the WordPress loading sequence.

Check back for the next post in this series where we’ll create a taxonomy, which is a way of grouping things together.

In the mean time please feel free to comment with your thoughts and opinions on how this content can be improved or extended. All feedback is welcomed 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.