Here’s an example of a custom post type for an “Example” CPT:
<?php
class CPT_Example
{
/**
* CPT_NAME is the custom post type name. Also used to generate the CPT Label using `ucfirst()`.
*
* @var string
*/
const CPT_NAME = 'example';
const TAX_NAME_TYPE = 'example-type';
const NONCE_NAME = 'example_meta_box';
public $fields = [
'example_name',
'example_company',
];
/**
* Set all the required hooks to register the Staff custom post type and all other required components/features
*
* @return void
*/
public function init()
{
// All the init operations we need to do in one call
add_action('init', [$this, 'register']);
// Remove the "Archive: " prefix (eg: "Archive: Staff Directory")
add_filter('get_the_archive_title_prefix', [$this, 'remove_archive_prefix'], 10, 1);
// Add a custom metabox for the example post type
add_action('add_meta_boxes', [$this, 'add_meta_boxes']);
}
/**
* Method to choreograph the registration of the custom post type and all of its required components
*
* @return void
*/
public function register()
{
$this->register_taxonomies();
$this->register_post_type();
add_action('save_post_' . self::CPT_NAME, [$this, 'save_example_meta']);
}
/**
* Registers the Staff custom post type
*
* @return void
*/
public function register_post_type()
{
$uc_label = ucwords(str_replace('-', ' ', self::CPT_NAME));
$uc_plural = $uc_label . 's';
register_post_type(
self::CPT_NAME,
[
'labels' => [
'name' => $uc_plural,
'singular_name' => $uc_label,
'menu_name' => $uc_label,
'parent_item_colon' => 'Parent ' . $uc_label,
'all_items' => 'All ' . $uc_plural,
'view_item' => 'View ' . $uc_label,
'add_new_item' => 'Add New ' . $uc_label,
'add_new' => 'Add New',
'edit_item' => 'Edit ' . $uc_label,
'update_item' => 'Update ' . $uc_label,
'search_items' => 'Search ' . $uc_plural,
'not_found' => 'Not Found',
'not_found_in_trash' => 'Not found in Trash',
],
'taxonomies' => [ self::TAX_NAME_TYPE, /* Add more taxonomies here */ ],
'show_ui' => true,
'public' => true,
'has_archive' => true,
'rewrite' => [
'slug' => self::CPT_NAME . 's',
'with_front' => false, // removes the /blog/ prefix in the url
'feeds' => false,
'pages' => true,
'ep_mask' => EP_PAGES
],
'menu_icon' => 'dashicons-businessman',
'supports' => ['title', 'editor', 'thumbnail'],
'show_in_rest' => true,
'rest_base' => self::CPT_NAME
]
);
}
public function register_taxonomies()
{
register_taxonomy(
self::TAX_NAME_TYPE,
self::CPT_NAME,
[
'labels' => [
'name' => 'Example Types',
'singular_name' => 'Example Type',
'search_items' => 'Search Example Types',
'all_items' => 'All Example Types',
'parent_item' => 'Parent Example Type',
'parent_item_colon' => 'Parent Example Type:',
'edit_item' => 'Edit Example Type',
'update_item' => 'Update Example Type',
'add_new_item' => 'Add New Example Type',
'new_item_name' => 'New Example Type Name',
'menu_name' => 'Example Types',
],
'show_ui' => true,
'show_admin_column' => true,
'hierarchical' => true,
'show_in_rest' => true,
'rest_base' => self::TAX_NAME_TYPE . 's'
]
);
}
/**
* Remove the "Archives:" prefix from the archive title for the post type
*
* @param string $prefix The current prefix as given by the filter
* @return string The modified prefix
*/
public function remove_archive_prefix($prefix)
{
return is_post_type_archive(self::CPT_NAME)
|| is_tax(self::TAX_NAME_TYPE)
? ''
: $prefix;
}
public function add_meta_boxes()
{
add_meta_box(
'example_posting_meta_box',
'Example Details',
[$this, 'render_example_meta_box'],
self::CPT_NAME,
'normal',
'high'
);
}
public function render_example_meta_box($post)
{
// Get existing meta values ('post' here means the object type comes from the posts table)
$meta = get_metadata( 'post', $post->ID, '', true );
foreach ( $this->fields as $field ) {
$$field = $meta[$field][0] ?? '';
}
// Add the hidden nonce field
wp_nonce_field( self::NONCE_NAME, self::NONCE_NAME . '_nonce');
include_once EXAMPLE_TEMPLATEDIR . 'metabox.php';
}
public function save_example_meta($post_id)
{
// Add nonce check, autosave check, and capability check here
$nonce = $_POST[self::NONCE_NAME . '_nonce'] ?? false;
if ( !$nonce || !wp_verify_nonce($nonce, self::NONCE_NAME) ) {
return $post_id;
}
foreach ( $this->fields as $field ) {
if (isset($_POST[$field])) {
update_post_meta($post_id, $field, $_POST[$field]);
}
}
}
}
Leave a Reply