Skip to content

Component Post_Type

alex_prokopenko edited this page Jan 17, 2018 · 4 revisions

Post_Type base class is used to make registration of post types more easy and more intuitive. It has a lot of constants defined to help IDE to suggest you available options and not to guess/google them.

Post_Type base class is defined in Objects\Post_Type.php class.

Why do you need to register a post type inside the code?

You can say, that there are a lot of plugins, which has admin interface to register a post type. -Yes, it's true. But let's check a bit deeper what we get with an additional plugin.

Each plugin with admin interface usually include a lot of code during the page load. To register a new post type it needs to check options from the database, parse them (unserialize) and only then it calls a registration function. Furthermore, good plugins has a lot of hooks inside, which added to make this plugin more flexible. And all this staff adds some time in your page load time. Good, optimized WordPress site has more than 10 3rd-party plugins. WordPress is not the fastest CMS in the world and you want to slow it down with one more plugin, because you're too lazy to write 20-30 lines of code?

Even if you use a plugin - all of them just repeat standard WordPress options and do not optimize anything in WordPress post types registration process.

We think registering post types inside the code for your theme is the only correct way of the development of a high-quality theme. That's why we prepared a base class to register a post type very fast and optimize some non-trivial options of WordPress register_post_type() function.

Usage instructions

To create a new post type you need to create your own class and extends it from JustCoded\WP\Framework\Objects\Post_Type. Inside init() method you should define Post_Type correct settings (with class properties) and call $this->register() at the end of the init().

Example:

<?php
namespace Boilerplate\Theme\Post_Type;

use JustCoded\WP\Framework\Objects\Post_Type;

class Employee extends Post_Type {
	/**
	 * ID
	 *
	 * @var string
	 */
	public static $ID = 'employee';

	/**
	 * Rewrite URL part
	 *
	 * @var string
	 */
	public static $SLUG = 'employee';

	/**
	 * Registration function
	 */
	public function init() {
		$this->label_singular = 'Employee';
		$this->label_multiple = 'Employees';
		$this->textdomain = 'boilerplate';

		$this->has_single       = true;
		$this->is_searchable    = true;
		$this->rewrite_singular = false;

		$this->is_hierarchical = false;

		$this->admin_menu_pos  = 25;
		$this->admin_menu_icon = 'dashicons-format-gallery';

		$this->taxonomies = array(
			'category',
		);

        // IT'S IMPORTANT TO CALL THIS METHOD, BECAUSE IT CALLS register_post_type() inside!
		$this->register();
	}
}

Most of the class properties duplicates configuration data you can pass to WordPress register_post_type() function. However there are few properties which makes easier to set correct values for some non-trivial options.

Activate registration

By default when you created a new class - it's not included anywhere inside the code and post type won't be added.

To do this - you need to create a new instance of your new class. This class implements Singleton design pattern, so creating an instance is available only through static instance() method.

If you use Theme class to register your theme features, then the code will be like this:

	/**
	 * Register post types
	 */
	public function register_post_types() {
		Employee::instance();
	}

New properties

A lot of mistakes in registering of the post types is usually made around such arguments:

  • public
  • publicly_queryable
  • show_in_nav_menus
  • exclude_from_search
  • has_archive
  • rewrite.with_front

Argument names are not very intuitive and understandable, without reading the documentation. We decide to make arguments much more intuitive. So we added logical properties, which are converted to the values for options above:

  • $has_single - means you have a singular template for your post type.
  • $has_archive - means you have a separate archive template for your post type.
  • $is_searchable - do you want this post type appears in a search results?
  • $rewrite_singular - make rewrite structure "singular" (do not include post type "slug" prefix).
  • $redirect - ability to redirect singular to another page (for example you want your post type to appears in the search results, but it doesn't have a singular template and you want to automatically redirect to an archive page).

Another group of non-intuitive options is:

  • show_ui
  • show_in_menu

Which is replaced with such property:

  • $has_admin_menu - set correct values for show_ui and show_in_menu.

Final arguments for register_post_types are generated with such peace of code:

<?php
...
$labels = array(
    'name'          => _x( $this->label_multiple, 'post type general name', $this->textdomain ),
    'singular_name' => _x( $this->label_singular, 'post type singular name', $this->textdomain ),
    'menu_name'     => _x( $this->label_multiple, 'admin menu', $this->textdomain ),
    'add_new'       => _x( 'Add New', $this->label_singular, $this->textdomain ),
);
$labels = array_merge( $labels, $this->labels );

$args = array(
    'labels'       => $labels,
    'hierarchical' => $this->is_hierarchical,

    'public'              => $this->has_single,
    'publicly_queryable'  => $this->has_single || $this->is_searchable || $this->redirect,
    'show_in_nav_menus'   => $this->has_single,
    'exclude_from_search' => ! $this->is_searchable,
    'has_archive'         => $this->has_archive,

    'show_ui'       => ! empty( $this->has_admin_menu ),
    'show_in_menu'  => $this->has_admin_menu,
    'menu_position' => $this->admin_menu_pos,
    'menu_icon'     => $this->admin_menu_icon,

    'capability_type' => $this->admin_capability,

    'supports' => $this->supports,

    'rewrite'   => array(
        'slug'       => $this::$SLUG,
        'with_front' => ( ! $this->rewrite_singular || $this->redirect ),
    ),
    'query_var' => $this->query_var,
);

if ( ! empty( $this->taxonomies ) && is_array( $this->taxonomies ) ) {
    $args['taxonomies'] = $this->taxonomies;
}

if ( ! empty( $this->capabilities ) ) {
    $args['capabilities'] = $this->capabilities;
}

Class reference

Properties

Property Type Default Description
static $ID string - Post_Type ID
static $SLUG string - Post_Type rewrite prefix, called slug
$label_singular string - Single Post Type label.
$label_multiple string - Multiple Post Type label.
$has_single bool false Has single page or not.
$is_searchable bool false Should appear in search results or not.
$is_hierarchical bool false Ability to set Parent.
$redirect bool|string false Specify where to redirect singular post type page.
$rewrite_singular bool false Simplify URLs structure and remove "slug" prefix from URL.
$has_admin_menu bool true Show in admin menu.
$admin_menu_pos int 25 Admin menu vertical position priority.
$admin_menu_icon string null Admin menu icon.
$supports array * Array of supported standard features of CPT.
*Adds title, editor, featured image and revisions by default.
$taxonomies array null Taxonomy IDs to add to this CPT, should be used only for standard Category and Tags..
$has_archive bool false Enable global archive page for CPT. We don't use it in Boilerplate.
$labels array [] Labels array to override auto-generated labels if needed.
$admin_capability string 'post' Main capability level.
$capabilities array null Custom capability options.
$query_var bool true Custom query var to be applied for single pages.
$textdomain string - Textdomain to apply to labels on post type registration.

Constants

There are a lot of constants to help you specify different option values or use them inside Models to be sure you don't misspell some parameter:

	const STATUS_ANY = 'any';
	const STATUS_DRAFT = 'draft';
	const STATUS_PENDING = 'pending';
	const STATUS_PUBLISH = 'publish';
	const STATUS_FUTURE = 'future';
	const STATUS_AUTO_DRAFT = 'auto-draft';
	const STATUS_PRIVATE = 'private';
	const STATUS_INHERIT = 'inherit';

	const SORT_ASC = 'asc';
	const SORT_DESC = 'desc';

	const ORDERBY_NONE = 'none';
	const ORDERBY_ID = 'ID';
	const ORDERBY_AUTHOR = 'author';
	const ORDERBY_TITLE = 'title';
	const ORDERBY_SLUG = 'name';
	const ORDERBY_TYPE = 'type';
	const ORDERBY_DATE = 'date';
	const ORDERBY_MODIFIED = 'modified';
	const ORDERBY_PARENT = 'parent';
	const ORDERBY_RAND = 'rand';
	const ORDERBY_COMMENTS = 'comment_count';
	const ORDERBY_WEIGHT = 'menu_order';
	const ORDERBY_META = 'meta_value';
	const ORDERBY_META_NUMERIC = 'meta_value_num';
	const ORDERBY_POST_IN = 'post__in';

	const SUPPORTS_TITLE = 'title';
	const SUPPORTS_EDITOR = 'editor';
	const SUPPORTS_AUTHOR = 'author';
	const SUPPORTS_FEATURED_IMAGE = 'thumbnail';
	const SUPPORTS_EXCERPT = 'excerpt';
	const SUPPORTS_TRACKBACKS = 'trackbacks';
	const SUPPORTS_CUSTOM_FIELDS = 'custom-fields';
	const SUPPORTS_COMMENTS = 'comments';  // (also will see comment count balloon on edit screen)
	const SUPPORTS_REVISIONS = 'revisions';
	const SUPPORTS_ORDER = 'page-attributes'; // (menu order, hierarchical must be true to show Parent option)
	const SUPPORTS_POST_FORMATS = 'post-formats';

Methods

Method / Called in Description
__construct Register init hook to run post types registration.
init
(a)init
Abstract method, you should define your own init method to register a post type.
register
init()
Main logic for registering a post type based on class properties
views
(a)template_include
Ability to update template hierarchy for specific post type.