The Codex page for register_taxonomy says that

This function adds or overwrites a taxonomy.

How can I use it to overwrite a core taxonomy without redefining all the parameters ?

For example, let's imagine that I want to make the core posts categories read-only for everybody. I can achieve that by setting the edit_terms capability for this taxonomy to do_not_allow.

My first guest was to call the register_taxonomy with only the parameter I want to change :

add_action( 'init', 'u16975_disable_category_creation' );
function u16975_disable_category_creation(){
    register_taxonomy( 'category', 'post', array(
        'capabilities' => array(
            'edit_terms' => 'do_not_allow',
    ) );

But this does not work as it also overwrites all other parameters and set them to the default value (ex: hierarchical is set back to false).

The only way I found to achieve this is to use the global variable that stores all registered taxonomies.

add_action( 'init', 'u16975_use_global_var' );
function u16975_use_global_var(){
    global $wp_taxonomies;
    $wp_taxonomies['category']->cap->edit_terms = 'do_not_allow';

Version 4.4 saw the introduction of the register_taxonomy_args filter in register_taxonomy() which you can use to filter the arguments used to register a taxonomy

 * Filter the arguments for registering a taxonomy.
 * @since 4.4.0
 * @param array  $args        Array of arguments for registering a taxonomy.
 * @param array  $object_type Array of names of object types for the taxonomy.
 * @param string $taxonomy    Taxonomy key.
$args = apply_filters( 'register_taxonomy_args', $args, $taxonomy, (array) $object_type );

So you can do the following:

add_filter( 'register_taxonomy_args', function ( $args, $taxonomy, $object_type )
    // Only target the built-in taxonomy 'category'
    if ( 'category' !== $taxonomy )
        return $args;

    // Set our capability 'edit_terms' to our value
    $args["capabilities"]["edit_terms"] = 'do_not_allow';

    return $args;
}, 10, 3);

On all older versions, you would either need to re-register the complete 'category' taxonomy or use the way you have done it in your question


The Codex page for register_taxonomy says that

  • This function adds or overwrites a taxonomy.

That is exactly what it does, it either creates a custom taxonomy or completely overrides and register a core taxonomy, it does not add any extra arguments to the existing taxonomy

  • Thanks for you answer Pieter. The filter you mentioned sounds interesting, but I'm still using 4.3 for a few days. Also the issue with this filter is that you have to register on it before the init hook, and in my case I want to execute this code only on a particular admin page, so I use the admin_head-$page_hook action. – Fabien Quatravaux Dec 14 '15 at 8:33
  • No problem. You shouldn't wait to long to upgrade as Version 4.4 offers quite a lot of new interesting features which you are missing out on :-) – Pieter Goosen Dec 14 '15 at 8:38

I found another reliable way to overwrite a taxonomy : I can just get the registered one before and change only the parameter I want. Registered taxonomies can be retrieved by get_taxonomy. But there are two catches :

  1. get_taxonomy returns an object, whereas register_taxonomy ask for an associative array, so we need a type cast.
  2. the capabilities parameter is stored as cap internally, so we need to change its name.

Here is the code :

add_action( 'init', 'u16975_disable_category_creation' );
function u16975_disable_category_creation(){
    $tax = get_taxonomy( 'category' );
    $tax->capabilities = (array)$tax->cap;
    $tax->capabilities['edit_terms'] = 'do_not_allow';
    register_taxonomy( 'category', 'post', (array)$tax );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.