Creating A Reusable Custom Post

By Top Pro Media Group Lead Developer

Custom post types are very useful for sites and blogs using the WordPress platform. Here at Top Pro Media Group we use them for industry specific galleries, case studies, staff members, etc. Anything you want loopable where you don’t want the person editing to be responsible for the layout of each item. Below I will show you step by step in the process of creating a base class that will create a new custom post type each time you call it. I prefer the class method as a variation on the idea of namespacing in other languages as you don’t have to worry about shared name violations.

In your theme’s functions.php file you’ll want to start with your typical class declaration:

class My_custom_post {
final function __construct() {}
}

This is just standard PHP initializing the class and the __construct function runs whenever a new My_custom_post is called. For this example, I like using the final declaration. We have no need to modify this class later on. What we will want to do is add a method to this class that will do WordPress API calls to actually register the custom post type.

class My_custom_post {
final function __construct() {}

final function register() {
register_post_type( $post_type , array() );
}
}

Here I am using the standard register_post_type via the WordPress Documentation. The idea is to pass a few items through the constructor so that we can add new post types with minimal effort. Basically we need a name, what it supports, custom taxonomies (tags/categories), and an icon. With WordPress, I’ve found it useful to pass both a singular name and a plural name. You could remove that requirement yourself, but then if you have a post type “Fish” you’ll see “Fishs” if you do a straight appending of an “s”. So next, we’ll set up the base variables and some defaults.

class My_custom_post {
private $singular = ‘New Post Type’;
private $plural = ‘New Post Types’;
private $tax = array(‘post_tag’,’category’);
private $supports = array(‘title’,’editor’,’thumbnail’,’page-attributes’);
private $menu_icon = null;

final function __construct() {}

final function register() {
register_post_type( $post_type , array() );
}
}

I like including these default taxonomies and support items just to cover the bases. In $supports, the ‘page-attributes’ will show the menu_order item when editing your post type. In doing so, you can query the custom post by menu_order. It has come in handy more often than not. The private declaration just keeps the variables modifiable by only this class. Speaking of, I should jump into showing how to modify this variables. To do this, we pass values through the constructor.

final function __construct(
$single = null,
$plural = null,
$supports = null,
$tax = null,
$menu_icon = null)
{
if ($single) $this->single = $single;
if ($plural) $this->plural = $plural;
if ($tax) $this->tax = $tax;
if ($supports) $this->supports = $supports;
if ($menu_icon) $this->menu_icon = $menu_icon;
}

What this code is telling us is that $single, $plural, $supports, $tax, and $menu_icon are all null. If we pass through a value new calling the class, it will replace the default variable we assigned previously (but just for this instance). This bit lets us call new My_custom_post(‘Dog’,’Dogs’); and new My_custom_post(‘Fish’,’Fish’); However, if you’re familiar with register_post_type you’ll know that neither name are valid when creating slugs. For that, we just need to perform some actions on the $single variable.

Add this to the private group at the top:

private $slug;

Then add this bit inside at the bottom of the __construct method:

$this->slug = preg_replace(“/[^a-z\-]/”,”,str_replace(‘ ‘,’-‘,strtolower($this->singular)));

That should create a suitable name for a slug.

Next we should jump into the the register_post_type function, since that is already discussed in full on WordPress Documentation, I’ll just show you how to integrate it into this class.

final function register() {
$labels = array(
‘name’ => _x($this->plural, $this->slug.’ general name’),
‘singular_name’ => _x($this->singular, $this->slug.’ singular name’),
‘add_new’ => _x(‘Add New’, $this->slug),
‘add_new_item’ => __(‘Add New ‘.$this->singular),
‘edit_item’ => __(‘Edit ‘.$this->singular),
‘new_item’ => __(‘New ‘.$this->singular),
‘view_item’ => __(‘View ‘.$this->singular),
‘search_items’ => __(‘Search ‘.$this->plural),
‘not_found’ => __(‘Nothing found’),
‘not_found_in_trash’ => __(‘Nothing found in Trash’),
‘parent_item_colon’ => ”
);

$args = array(
‘labels’ => $labels,
‘public’ => true,
‘publicly_queryable’ => true,
‘show_ui’ => true,
‘query_var’ => true,
‘rewrite’ => true,
‘capability_type’ => ‘post’,
‘hierarchical’ => false,
‘menu_position’ => null,
‘supports’ => $this->supports,
‘taxonomies’ => $this->tax
);

if ($this->menu_icon) {
$args[‘menu_icon’] = $this->menu_icon;
}

register_post_type( $this->slug , $args );
}

What I am doing is taking the variables we initialized at the top as private and putting them where they go for the register_post_type function. I should note that if $menu_icon is null, WordPress uses the default pushpin.

Then we need to add this method to the init action so that this method is called. WordPress’s add_action supports wrapping within classes so this is a simple endeavor. Put the following snipit at the end of the __construct method:

add_action(‘init’, array($this, ‘register’));

This actually adds register() to the init and we pass it as an array referencing My_custom_post as $this at index 0.

That’s all there is to it. Now when you add new My_custom_post(); to your functions.php file, it will create a new post_type in the WordPress backend titled “New Post Types”. So essentially you could create the following:

new My_custom_post(‘Staff’,’Staff’);
new My_custom_post(‘Testimonial’,’Testimonials’);
new My_custom_post(‘Review’,’Reviews’);
new My_custom_post(‘Letter’,’Letters’);

And each of those will show up under the Comments section inside your WP Admin area.

Finally, here’s the entire code:

class My_custom_post {
private $singular = ‘New Post Type’;
private $plural = ‘New Post Types’;
private $tax = array(‘post_tag’,’category’);
private $supports = array(‘title’,’editor’,’thumbnail’,’page-attributes’);
private $menu_icon = null;
private $slug;

final function __construct(
$single = null,
$plural = null,
$supports = null,
$tax = null,
$menu_icon = null)
{
if ($single) $this->single = $single;
if ($plural) $this->plural = $plural;
if ($tax) $this->tax = $tax;
if ($supports) $this->supports = $supports;
if ($menu_icon) $this->menu_icon = $menu_icon;

$this->slug = preg_replace(“/[^a-z\-]/”,”,str_replace(‘ ‘,’-‘,strtolower($this->singular)));

add_action(‘init’, array($this, ‘register’));
}
final function register() {
$labels = array(
‘name’ => _x($this->plural, $this->slug.’ general name’),
‘singular_name’ => _x($this->singular, $this->slug.’ singular name’),
‘add_new’ => _x(‘Add New’, $this->slug),
‘add_new_item’ => __(‘Add New ‘.$this->singular),
‘edit_item’ => __(‘Edit ‘.$this->singular),
‘new_item’ => __(‘New ‘.$this->singular),
‘view_item’ => __(‘View ‘.$this->singular),
‘search_items’ => __(‘Search ‘.$this->plural),
‘not_found’ => __(‘Nothing found’),
‘not_found_in_trash’ => __(‘Nothing found in Trash’),
‘parent_item_colon’ => ”
);

$args = array(
‘labels’ => $labels,
‘public’ => true,
‘publicly_queryable’ => true,
‘show_ui’ => true,
‘query_var’ => true,
‘rewrite’ => true,
‘capability_type’ => ‘post’,
‘hierarchical’ => false,
‘menu_position’ => null,
‘supports’ => $this->supports,
‘taxonomies’ => $this->tax
);

if ($this->menu_icon) {
$args[‘menu_icon’] = $this->menu_icon;
}

register_post_type( $this->slug , $args );
}
}