This function adds or overwrites a taxonomy. It takes in a name, an object name that it affects, and an array of parameters. It does not return anything.
Care should be used in selecting a taxonomy name so that it does not conflict with other taxonomies, post types, and reserved WordPress public and private query variables. A complete list of those is described in the Reserved Terms section. In particular, capital letters should be avoided.
Better be safe than sorry when registering custom taxonomies for custom post types. Use register_taxonomy_for_object_type() right after the function to interconnect them. Else you could run into minetraps where the post type isn’t attached inside filter callback that run during parse_request or pre_get_posts.
- $taxonomy is the name of the taxonomy. Name should only contain lowercase letters and the underscore character, and not be more than 32 characters long (database structure restriction). Default: None
- $object_type is the name of the object type for the taxonomy object. Object-types can be built-in Post Type or any Custom Post Type that may be registered. Default is None.
- Built-in Post Types:
- post
- page
- attachment
- revision
- nav_menu_item
- custom_css
- customize_changeset
- Custom Post Types:
- {custom_post_type} – Custom Post Type names must be all in lower-case and without any spaces.
- null – Setting explicitly to null registers the taxonomy but doesn’t associate it with any objects, so it won’t be directly available within the Admin UI. You will need to manually register it using the ‘taxonomy’ parameter (passed through $args) when registering a custom post_type (see register_post_type()), or using register_taxonomy_for_object_type().
- $args
- (array/string) (optional) An array of Arguments.
- Default: None
- label
- (string) (optional) A plural descriptive name for the taxonomy marked for translation.
- Default: overridden by $labels->name
- labels
- (array) (optional) labels – An array of labels for this taxonomy. By default tag labels are used for non-hierarchical types and category labels for hierarchical ones.
- Default: if empty, name is set to label value, and singular_name is set to name value
- ‘name’ – general name for the taxonomy, usually plural. The same as and overridden by $tax->label. Default is
_x( 'Post Tags', 'taxonomy general name' ) or _x( 'Categories', 'taxonomy general name' ). When internationalizing this string, please use a gettext context matching your post type. Example: _x('Writers', 'taxonomy general name');
- ‘singular_name’ – name for one object of this taxonomy. Default is
_x( 'Post Tag', 'taxonomy singular name' ) or _x( 'Category', 'taxonomy singular name' ). When internationalizing this string, please use a gettext context matching your post type. Example: _x('Writer', 'taxonomy singular name');
- ‘menu_name’ – the menu name text. This string is the name to give menu items. If not set, defaults to value of name label.
- ‘all_items’ – the all items text. Default is
__( 'All Tags' ) or __( 'All Categories' )
- ‘edit_item’ – the edit item text. Default is
__( 'Edit Tag' ) or __( 'Edit Category' )
- ‘view_item’ – the view item text, Default is
__( 'View Tag' ) or __( 'View Category' )
- ‘update_item’ – the update item text. Default is
__( 'Update Tag' ) or __( 'Update Category' )
- ‘add_new_item’ – the add new item text. Default is
__( 'Add New Tag' ) or __( 'Add New Category' )
- ‘new_item_name’ – the new item name text. Default is
__( 'New Tag Name' ) or __( 'New Category Name' )
- ‘parent_item’ – the parent item text. This string is not used on non-hierarchical taxonomies such as post tags. Default is null or
__( 'Parent Category' )
- ‘parent_item_colon’ – The same as
parent_item, but with colon : in the end null, __( 'Parent Category:' )
- ‘search_items’ – the search items text. Default is
__( 'Search Tags' ) or __( 'Search Categories' )
- ‘popular_items’ – the popular items text. This string is not used on hierarchical taxonomies. Default is
__( 'Popular Tags' ) or null
- ‘separate_items_with_commas’ – the separate item with commas text used in the taxonomy meta box. This string is not used on hierarchical taxonomies. Default is
__( 'Separate tags with commas' ), or null
- ‘add_or_remove_items’ – the add or remove items text and used in the meta box when JavaScript is disabled. This string is not used on hierarchical taxonomies. Default is
__( 'Add or remove tags' ) or null
- ‘choose_from_most_used’ – the choose from most used text used in the taxonomy meta box. This string is not used on hierarchical taxonomies. Default is
__( 'Choose from the most used tags' ) or null
- ‘not_found’ (3.6+) – the text displayed via clicking ‘Choose from the most used tags’ in the taxonomy meta box when no tags are available and (4.2+) – the text used in the terms list table when there are no items for a taxonomy. Default is
__( 'No tags found.' ) or __( 'No categories found.' )
- ‘back_to_items’ – the text displayed after a term has been updated for a link back to main index. Default is
__( 'β Back to tags' ) or __( 'β Back to categories' )
- public
- (boolean) (optional) Whether a taxonomy is intended for use publicly either via the admin interface or by front-end users. The default settings of `$publicly_queryable`, `$show_ui`, and `$show_in_nav_menus` are inherited from `$public`.
- Default: true
- publicly_queryable
- (boolean) (optional) Whether the taxonomy is publicly queryable.
- Default: $public
- show_ui
- (boolean) (optional) Whether to generate a default UI for managing this taxonomy.
- Default: if not set, defaults to value of public argument. As of 3.5, setting this to false for attachment taxonomies will hide the UI.
- show_in_nav_menus
- (boolean) (optional) true makes this taxonomy available for selection in navigation menus.
- Default: if not set, defaults to value of public argument
- show_in_rest
- (boolean) (optional) Whether to include the taxonomy in the REST API. You will need to set this to true in order to use the taxonomy in your gutenberg metablock.
- Default: false
- rest_base
- (string) (optional) To change the base url of REST API route.
- Default: $taxonomy
- rest_controller_class
- (string) (optional) REST API Controller class name.
- Default: WP_REST_Terms_Controller
- show_tagcloud
- (boolean) (optional) Whether to allow the Tag Cloud widget to use this taxonomy.
- Default: if not set, defaults to value of show_ui argument
- show_in_quick_edit
- (boolean) (optional) Whether to show the taxonomy in the quick/bulk edit panel. (Available since 4.2)
- Default: if not set, defaults to value of show_ui argument
- meta_box_cb
- (callback) (optional) Provide a callback function name for the meta box display. (Available since 3.8)
- Default: null
Note: Defaults to the categories meta box (post_categories_meta_box() in meta-boxes.php) for hierarchical taxonomies and the tags meta box (post_tags_meta_box() ) for non-hierarchical taxonomies. No meta box is shown if set to false.
- show_admin_column
- (boolean) (optional) Whether to allow automatic creation of taxonomy columns on associated post-types table. (Available since 3.5)
- Default: false
- description
- (string) (optional) Include a description of the taxonomy.
- Default: “”
- hierarchical
- (boolean) (optional) Is this taxonomy hierarchical (have descendants) like categories or not hierarchical like tags.
- Default: false
Note: Hierarchical taxonomies will have a list with checkboxes to select an existing category in the taxonomy admin box on the post edit page (like default post categories). Non-hierarchical taxonomies will just have an empty text field to type-in taxonomy terms to associate with the post (like default post tags).
- update_count_callback
- (string) (optional) A function name that will be called when the count of an associated $object_type, such as post, is updated. Works much like a hook.
- Default: None – but see Note, below.
Note: While the default is '', when actually performing the count update in wp_update_term_count_now() , if the taxonomy is only attached to post types (as opposed to other WordPress objects, like user), the built-in _update_post_term_count() function will be used to count only published posts associated with that term, otherwise _update_generic_term_count() will be used instead, that does no such checking.
This is significant in the case of attachments. Because an attachment is a type of post, the default _update_post_term_count() will be used. However, this may be undesirable, because this will only count attachments that are actually attached to another post (like when you insert an image into a post). This means that attachments that you simply upload to WordPress using the Media Library, but do not actually attach to another post will not be counted. If your intention behind associating a taxonomy with attachments was to leverage the Media Library as a sort of Document Management solution, you are probably more interested in the counts of unattached Media items, than in those attached to posts. In this case, you should force the use of _update_generic_term_count() by setting ‘_update_generic_term_count’ as the value for update_count_callback.
Another important consideration is that _update_post_term_count() only counts published posts. If you are using custom statuses, or using custom post types where being published is not necessarily a consideration for being counted in the term count, then you will need to provide your own callback that doesn’t include the post_status portion of the where clause.
- query_var
- (boolean or string) (optional) False to disable the query_var, set as string to use custom query_var instead of default which is $taxonomy, the taxonomy’s “name”. True is not seen as a valid entry and will result in 404 issues.
- Default: $taxonomy
Note: The query_var is used for direct queries through WP_Query like new WP_Query(array('people'=>$person_name)) and URL queries like /?people=$person_name. Setting query_var to false will disable these methods, but you can still fetch posts with an explicit WP_Query taxonomy query like WP_Query(array('taxonomy'=>'people', 'term'=>$person_name)).
- rewrite
- (boolean/array) (optional) Set to false to prevent automatic URL rewriting a.k.a. “pretty permalinks”. Pass an $args array to override default URL settings for permalinks as outlined below:
- Default: true
- ‘slug’ – Used as pretty permalink text (i.e. /tag/) – defaults to $taxonomy (taxonomy’s name slug)
- ‘with_front’ – allowing permalinks to be prepended with front base – defaults to true
- ‘hierarchical’ – true or false allow hierarchical urls (implemented in Version 3.1) – defaults to false
- ‘ep_mask’ – (Required for pretty permalinks) Assign an endpoint mask for this taxonomy – defaults to EP_NONE. If you do not specify the EP_MASK, pretty permalinks will not work. For more info see this Make WordPress Plugins summary of endpoints.
Note: You may need to flush the rewrite rules after changing this. You can do it manually by going to the Permalink Settings page and re-saving the rules — you don’t need to change them — or by calling $wp_rewrite::flush_rules(). You should only flush the rules once after the taxonomy has been created, not every time the plugin/theme loads.
- capabilities
- (array) (optional) An array of the capabilities for this taxonomy.
- Default: None
- ‘manage_terms’ – ‘manage_categories’
- ‘edit_terms’ – ‘manage_categories’
- ‘delete_terms’ – ‘manage_categories’
- ‘assign_terms’ – ‘edit_posts’
- sort
- (boolean) (optional) Whether this taxonomy should remember the order in which terms are added to objects.
- Default: None
- _builtin
- (boolean) (not for general use) Whether this taxonomy is a native or “built-in” taxonomy. Note: this entry is for documentation – core developers recommend you don’t use this when registering your own taxonomy
- Default: false
Avoiding the following reserved terms is particularly important if you are passing the term through the $_GET or $_POST array. Doing so can cause WordPress to respond with a 404 error without any other hint or explanation.
- attachment
- attachment_id
- author
- author_name
- calendar
- cat
- category
- category__and
- category__in
- category__not_in
- category_name
- comments_per_page
- comments_popup
- custom
- customize_messenger_channel
- customized
- cpage
- day
- debug
- embed
- error
- exact
- feed
- fields
- hour
- link_category
- m
- minute
- monthnum
- more
- name
- nav_menu
- nonce
- nopaging
- offset
- order
- orderby
- p
- page
- page_id
- paged
- pagename
- pb
- perm
- post
- post__in
- post__not_in
- post_format
- post_mime_type
- post_status
- post_tag
- post_type
- posts
- posts_per_archive_page
- posts_per_page
- preview
- robots
- s
- search
- second
- sentence
- showposts
- static
- status
- subpost
- subpost_id
- tag
- tag__and
- tag__in
- tag__not_in
- tag_id
- tag_slug__and
- tag_slug__in
- taxonomy
- tb
- term
- terms
- theme
- title
- type
- types
- w
- withcomments
- withoutcomments
- year
function register_taxonomy( $taxonomy, $object_type, $args = array() ) {
global $wp_taxonomies;
if ( ! is_array( $wp_taxonomies ) ) {
$wp_taxonomies = array();
}
$args = wp_parse_args( $args );
if ( empty( $taxonomy ) || strlen( $taxonomy ) > 32 ) {
_doing_it_wrong( __FUNCTION__, __( 'Taxonomy names must be between 1 and 32 characters in length.' ), '4.2.0' );
return new WP_Error( 'taxonomy_length_invalid', __( 'Taxonomy names must be between 1 and 32 characters in length.' ) );
}
$taxonomy_object = new WP_Taxonomy( $taxonomy, $object_type, $args );
$taxonomy_object->add_rewrite_rules();
$wp_taxonomies[ $taxonomy ] = $taxonomy_object;
$taxonomy_object->add_hooks();
// Add default term.
if ( ! empty( $taxonomy_object->default_term ) ) {
$term = term_exists( $taxonomy_object->default_term['name'], $taxonomy );
if ( $term ) {
update_option( 'default_term_' . $taxonomy_object->name, $term['term_id'] );
} else {
$term = wp_insert_term(
$taxonomy_object->default_term['name'],
$taxonomy,
array(
'slug' => sanitize_title( $taxonomy_object->default_term['slug'] ),
'description' => $taxonomy_object->default_term['description'],
)
);
// Update `term_id` in options.
if ( ! is_wp_error( $term ) ) {
update_option( 'default_term_' . $taxonomy_object->name, $term['term_id'] );
}
}
}
/**
* Fires after a taxonomy is registered.
*
* @since 3.3.0
*
* @param string $taxonomy Taxonomy slug.
* @param array|string $object_type Object type or array of object types.
* @param array $args Array of taxonomy registration arguments.
*/
do_action( 'registered_taxonomy', $taxonomy, $object_type, (array) $taxonomy_object );
/**
* Fires after a specific taxonomy is registered.
*
* The dynamic portion of the filter name, `$taxonomy`, refers to the taxonomy key.
*
* Possible hook names include:
*
* - `registered_taxonomy_category`
* - `registered_taxonomy_post_tag`
*
* @since 6.0.0
*
* @param string $taxonomy Taxonomy slug.
* @param array|string $object_type Object type or array of object types.
* @param array $args Array of taxonomy registration arguments.
*/
do_action( "registered_taxonomy_{$taxonomy}", $taxonomy, $object_type, (array) $taxonomy_object );
return $taxonomy_object;
}