Registers a post type.
Note: Post type registrations should not be hooked before the ‘init’ action. Also, any taxonomy connections should be registered via the $taxonomies argument to ensure consistency when hooks such as ‘parse_query’ or ‘pre_get_posts’ are used.
Post types can support any number of built-in core features such as meta boxes, custom fields, post thumbnails, post statuses, comments, and more. See the $supports argument for a complete list of supported features.
$post_typestringrequired
$argsarray|stringoptional
label string'name'].labels string[]description stringpublic boolhierarchical boolexclude_from_search boolpublicly_queryable boolshow_ui boolshow_in_menu bool|string'tools.php' or 'edit.php?post_type=page', for example), the post type will be placed as a sub-menu of that.show_in_nav_menus boolshow_in_admin_bar boolshow_in_rest boolrest_base stringrest_namespace stringrest_controller_class stringautosave_rest_controller_class string|boolrevisions_rest_controller_class string|boollate_route_registration boolmenu_position intmenu_icon string'data:image/svg+xml;base64,'. Pass the name of a Dashicons helper class to use a font icon, e.g.'dashicons-chart-pie'. Pass 'none' to leave div.wp-menu-image empty so an icon can be added via CSS. Defaults to use the posts icon.capability_type string|array'story', 'stories'). Default 'post'.capabilities string[]map_meta_cap boolsupports array|false'title', 'editor', 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', 'page-attributes', 'thumbnail', 'custom-fields', and 'post-formats'.'revisions' feature dictates whether the post type will store revisions, the 'autosave' feature dictates whether the post type will be autosaved, and the 'comments' feature dictates whether the comments count will show on the edit screen. For backward compatibility reasons, adding 'editor' support implies 'autosave' support too. A feature can also be specified as an array of arguments to provide additional information about supporting that feature.array( 'my_feature', array( 'field' => 'value' ) ).'title' and 'editor'.register_meta_box_cb callabletaxonomies string[]has_archive bool|stringrewrite bool|arrayslug stringwith_front boolfeeds boolpages boolep_mask intquery_var string|boolcan_export booldelete_with_user bool'author' feature. Otherwise posts are not trashed or deleted.template arraytemplate_lock string|false'all', the user is unable to insert new blocks, move existing blocks and delete blocks.'insert', the user is able to move existing blocks but is unable to insert new blocks and delete blocks._builtin bool_edit_link string'post.php?post=%d'.Default:array()
You can use this function in themes and plugins. However, if you use it in a theme, your post type will disappear from the admin if a user switches away from your theme. See Must Use Plugins If you want to keep your changes e.g. post type, even if you switch between your themes.
When registering a post type, always register your taxonomies using the taxonomies argument. If you do not, the taxonomies and post type will not be recognized as connected when using filters such as parse_query or pre_get_posts. This can lead to unexpected results and failures.
Even if you register a taxonomy while creating the post type, you must still explicitly register and define the taxonomy using register_taxonomy().
The following post types are reserved and are already used by WordPress.
In addition, the following post types should not be used as they interfere with other WordPress functions.
In general, you should always prefix your post types, or specify a custom `query_var`, to avoid conflicting with existing WordPress query variables.
More information: Post Types.
The only way to read that field is using this code:
$obj = get_post_type_object( 'your_post_type_name' ); echo esc_html( $obj->description );
show_in_nav_menus, show_ui) and readers (exclude_from_search, publicly_queryable). exclude_from_search: false, publicly_queryable: true, show_in_nav_menus: true, and show_ui:true. The built-in types attachment, page, and post are similar to this.exclude_from_search: true, publicly_queryable: false, show_in_nav_menus: false, and show_ui: false. The built-in types nav_menu_item and revision are similar to this. Best used if you’ll provide your own editing and viewing interfaces (or none at all).exclude_from_search, publicly_queryable, show_in_nav_menus, or show_ui, they inherit their values from public.'capabilities' => array( 'edit_post' => 'edit_book', 'read_post' => 'read_book', 'delete_post' => 'delete_book', 'edit_posts' => 'edit_books', 'edit_others_posts' => 'edit_others_books', 'publish_posts' => 'publish_books', 'read_private_posts' => 'read_private_books', 'create_posts' => 'edit_books', ),
[cap] => stdClass Object ( // Meta capabilities [edit_post] => edit_book [read_post] => read_book [delete_post] => delete_book // Primitive capabilities used outside of map_meta_cap(): [edit_posts] => edit_books [edit_others_posts] => edit_others_books [publish_posts] => publish_books [read_private_posts] => read_private_books // Primitive capabilities used within map_meta_cap(): [create_posts] => edit_books )
create_posts is automatically mapped to edit_posts by default.map_meta_cap‘ argument set to true (default is false). If you assign a 'capability_type' and then take a look into the $GLOBALS['wp_post_types']['your_cpt_name'] array, then you’ll see the following:
[cap] => stdClass Object
(
// Meta capabilities
[edit_post] => "edit_{$capability_type}"
[read_post] => "read_{$capability_type}"
[delete_post] => "delete_{$capability_type}"
// Primitive capabilities used outside of map_meta_cap():
[edit_posts] => "edit_{$capability_type}s"
[edit_others_posts] => "edit_others_{$capability_type}s"
[publish_posts] => "publish_{$capability_type}s"
[read_private_posts] => "read_private_{$capability_type}s"
// Primitive capabilities used within map_meta_cap():
[read] => "read",
[delete_posts] => "delete_{$capability_type}s"
[delete_private_posts] => "delete_private_{$capability_type}s"
[delete_published_posts] => "delete_published_{$capability_type}s"
[delete_others_posts] => "delete_others_{$capability_type}s"
[edit_private_posts] => "edit_private_{$capability_type}s"
[edit_published_posts] => "edit_published_{$capability_type}s"
[create_posts] => "edit_{$capability_type}s"
)
Note the “s” at the end of plural capabilities.
category or post_tag that will be used with this post type. This can be used in lieu of calling register_taxonomy_for_object_type() directly. Custom taxonomies still need to be registered with register_taxonomy(). To get permalinks to work when you activate the plugin use the following example, paying attention to how my_cpt_init() is called in the register_activation_hook callback:
add_action( 'init', 'my_cpt_init' );
function my_cpt_init() {
register_post_type( ... );
}
register_activation_hook( __FILE__, 'my_rewrite_flush' );
function my_rewrite_flush() {
// First, we "add" the custom post type via the above written function.
// Note: "add" is written with quotes, as CPTs don't get added to the DB,
// They are only referenced in the post_type column with a post entry,
// when you add a post of this CPT.
my_cpt_init();
// ATTENTION: This is *only* done during plugin activation hook in this example!
// You should *NEVER EVER* do this on every page load!!
flush_rewrite_rules();
} For themes, you’ll need to use the after_switch_theme hook instead. Like so:
add_action( 'init', 'my_cpt_init' );
function my_cpt_init() {
register_post_type( ... );
}
add_action( 'after_switch_theme', 'my_rewrite_flush' );
function my_rewrite_flush() {
my_cpt_init();
flush_rewrite_rules();
} Note that although the $public attribute is optional, the inputs passed to the register_post_type() function are exactly what is queried by the get_post_types() function. So if you verbosely set the equivalent options for publicly_queriable, show_ui, show_in_nav_menus, and exclude_from_search, this will not be handled the same as if you had set the $public attribute. See bug 18950.
function register_post_type( $post_type, $args = array() ) {
global $wp_post_types;
if ( ! is_array( $wp_post_types ) ) {
$wp_post_types = array();
}
// Sanitize post type name.
$post_type = sanitize_key( $post_type );
if ( empty( $post_type ) || strlen( $post_type ) > 20 ) {
_doing_it_wrong( __FUNCTION__, __( 'Post type names must be between 1 and 20 characters in length.' ), '4.2.0' );
return new WP_Error( 'post_type_length_invalid', __( 'Post type names must be between 1 and 20 characters in length.' ) );
}
$post_type_object = new WP_Post_Type( $post_type, $args );
$post_type_object->add_supports();
$post_type_object->add_rewrite_rules();
$post_type_object->register_meta_boxes();
$wp_post_types[ $post_type ] = $post_type_object;
$post_type_object->add_hooks();
$post_type_object->register_taxonomies();
/**
* Fires after a post type is registered.
*
* @since 3.3.0
* @since 4.6.0 Converted the `$post_type` parameter to accept a `WP_Post_Type` object.
*
* @param string $post_type Post type.
* @param WP_Post_Type $post_type_object Arguments used to register the post type.
*/
do_action( 'registered_post_type', $post_type, $post_type_object );
/**
* Fires after a specific post type is registered.
*
* The dynamic portion of the filter name, `$post_type`, refers to the post type key.
*
* Possible hook names include:
*
* - `registered_post_type_post`
* - `registered_post_type_page`
*
* @since 6.0.0
*
* @param string $post_type Post type.
* @param WP_Post_Type $post_type_object Arguments used to register the post type.
*/
do_action( "registered_post_type_{$post_type}", $post_type, $post_type_object );
return $post_type_object;
}
Fires after a post type is registered.
Fires after a specific post type is registered.
| Version | Description |
|---|---|
| 5.9.0 | The rest_namespace argument was added. |
| 5.3.0 | The supports argument will now accept an array of arguments for a feature. |
| 5.0.0 | The template and template_lock arguments were added. |
| 4.7.0 | Introduced show_in_rest, rest_base and rest_controller_class arguments to register the post type in REST API. |
| 4.6.0 | Post type object returned is now an instance of WP_Post_Type. |
| 4.4.0 | The show_ui argument is now enforced on the post type listing screen and post editing screen. |
| 3.0.0 | The show_ui argument is now enforced on the new post screen. |
| 2.9.0 | Introduced. |
You must log in before being able to contribute a note or feedback.
© 2003–2024 WordPress Foundation
Licensed under the GNU GPLv2+ License.
https://developer.wordpress.org/reference/functions/register_post_type