Skip to content

WordPress Patterns – An Elegant way to create a Custom Post Type

I would like to share a simple design pattern that I follow when programmatically creating custom post types in WordPress. This solution is fairly elegant.


  • It’s re-usable
  • It’s easy to modify and scale
  • It’s easy to read

The same pattern can be used for other things as well such as shortcodes and taxonomies but more on that later.

Pretty much all of the time when developing bespoke themes for WordPress I take an Object Oriented approach which enables me to compartmentalise things like post type or taxonomy registration.

Generally, I’d create a directory named post-type and create a file in that which contains the name of the post type followed by pt.php.
So – post-type/

There are some variables declared at the top of the class which contain some common things that can be quickly changed if this code was to be re-used for another post type – all for speed.

You’ll notice that the code begins by using the PostType namespace. This is because I can name the class Event without fear of conflicting class names. If I wanted to use methods from this class in other template files I would be able to do something like.

// OR (accessing a static method)
$events = \PostType\Event::get_events();
// OR (instantiating new object and accessing one of its public methods)
$eventObj = new \PostType\Event();
$events = $eventObj->get_events();

The code below is well commented. Fill in the gaps with your own code. You’ll see the admin post table column action
and filter
have been mapped to methods ready for code.

 * Use namespace to avoid conflict
namespace PostType;
 * Class Event
 * @package PostType
 * Use actual name of post type for
 * easy readability.
 * Potential conflicts removed by namespace
class Event {
     * @var string
     * Set post type params
    private $type               = 'event';
    private $slug               = 'events';
    private $name               = 'Events';
    private $singular_name      = 'Event';
     * Register post type
    public function register() {
        $labels = array(
            'name'                  => $this->name,
            'singular_name'         => $this->singular_name,
            'add_new'               => 'Add New',
            'add_new_item'          => 'Add New '   . $this->singular_name,
            'edit_item'             => 'Edit '      . $this->singular_name,
            'new_item'              => 'New '       . $this->singular_name,
            'all_items'             => 'All '       . $this->name,
            'view_item'             => 'View '      . $this->name,
            'search_items'          => 'Search '    . $this->name,
            'not_found'             => 'No '        . strtolower($this->name) . ' found',
            'not_found_in_trash'    => 'No '        . strtolower($this->name) . ' found in Trash',
            'parent_item_colon'     => '',
            'menu_name'             => $this->name
        $args = array(
            'labels'                => $labels,
            'public'                => true,
            'publicly_queryable'    => true,
            'show_ui'               => true,
            'show_in_menu'          => true,
            'query_var'             => true,
            'rewrite'               => array( 'slug' => $this->slug ),
            'capability_type'       => 'post',
            'has_archive'           => true,
            'hierarchical'          => true,
            'menu_position'         => 8,
            'supports'              => array( 'title', 'editor', 'excerpt', 'author', 'thumbnail'),
            'yarpp_support'         => true
        register_post_type( $this->type, $args );
     * @param $columns
     * @return mixed
     * Choose the columns you want in
     * the admin table for this post
    public function set_columns($columns) {
        // Set/unset post type table columns here
        return $columns;
     * @param $column
     * @param $post_id
     * Edit the contents of each column in
     * the admin table for this post
    public function edit_columns($column, $post_id) {
        // Post type table column content code here
     * Event constructor.
     * When class is instantiated
    public function __construct() {
        // Register the post type
        add_action('init', array($this, 'register'));
        // Admin set post columns
        add_filter( 'manage_edit-'.$this->type.'_columns',        array($this, 'set_columns'), 10, 1) ;
        // Admin edit post columns
        add_action( 'manage_'.$this->type.'_posts_custom_column', array($this, 'edit_columns'), 10, 2 );
 * Instantiate class, creating post type
new Event();


10 years + experience in web development working with lots of different technology.

Published inWeb DesignWordPress

One Comment

  1. Pablo Pablo

    Can you show me how to unit-test this class?? This week I am trying to found an elegant way to create custom_post_types from my plugin. I was thinking about having one class and an array and do foreach. This class can be extended to specific custom post type if needed (class_exist).

    My first approach was like yours. With new at the end and hooks on the constructor, but I do not think this can be unit-test. Isolation principle.

    Second approach. Having same hooks code on init method instead of constructor. Init method can be unit-test.

Leave a Reply

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