WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I was wondering if there was a way to prevent the addition of new categories into a taxonomy, essentially 'locking' the taxonomy.

I'm programatically registering a taxonomy and filling it with terms via functions.php and would like it so you cannot add anymore into it.

The Vision, REALIZED...

Heres how my solution ended up looking, and it works great! THANKS to everyone who helped. Upvotes all over the place up in your face!

// some stuff happens before this...
    $labels = array(
        'name' => _x( 'Attendees', 'taxonomy general name' ),
        'singular_name' => _x( 'Attendee', 'taxonomy singular name' ),
        'search_items' =>  __( 'Search Attendees' ),
        'all_items' => __( 'All Attendees' ),
        'edit_item' => __( 'Edit Attendee' ), 
        'update_item' => __( 'Update Attendee' ),
        'add_new_item' => __( 'Add New Attendee' ),
        'new_item_name' => __( 'New Attendee Name' ),
        'menu_name' => __( 'Attendees' )
    $rewrite = array(
        'slug' => 'attendee'
    $capabilities = array(
        'manage_terms' => 'nobody',
        'edit_terms' => 'nobody',
        'delete_terms' => 'nobody',
        'assign_terms' => 'nobody'
    $args = array(
        'hierarchical' => true,
        'labels' => $labels,
        'show_ui' => true,
        'query_var' => 'attendee',
        'rewrite' => $rewrite,
        'capabilities' => $capabilities
    register_taxonomy('attendees', 'meetings', $args);
add_action( 'init', 'todo_create_taxonomies', 1);
function todo_register_attendees() {
    $users = get_users();
    foreach ( $users as $user ) {
        wp_insert_term( $user->display_name, 'attendees', array('description'=> $user->display_name, 'slug' => $user->user_nicename) );
        $lockdown[] = $user->user_nicename;
    $terms = get_terms('attendees', array('get' => 'all') );
    foreach ($terms as $term) {
        if ( !in_array($term->slug, $lockdown) ) {
            wp_delete_term( $term->term_id, 'attendees' );
            $message = new WP_Error('force_terms', __('Only Registered Users can be Attendees, ' . $term->name . ' has been deleted.'));
            if ( is_wp_error($message) ) { ?>
                <div id="aphid-error-<?php echo $message->get_error_code(); ?>" class="error aphid-error"> 
                    <p><strong><?php echo $message->get_error_message(); ?></strong></p>
            <?php }
add_action( 'admin_notices', 'todo_register_attendees' );
share|improve this question
+1 waiting for answer – Ünsal Korkmaz Apr 9 '11 at 8:52
up vote 3 down vote accepted

Categories, Tags & Taxonomies

First i want to make this one clear: Everything is a Taxonomy. Tags is a non-hierarchical, Categories a hierarchical and both are built-in taxonomies. Same goes for eg. post formats (aside, chat, etc.). It's the same concept as with post-types (post, page, attachment, nav_menu_item, etc. are all just built in post types).

Everything inside one of those Taxonomies is a Term. For eg. (inside post formats) "aside", "quote", "audio".

Codex Links

The Concept

The following is for your functions.php file. This triggers on every page request. You could improve it - using the Transients API - to trigger on given timestamps (eg. twice daily, hourly, etc.).

function wpse14350_cleanup_taxonomy_terms()
    // Define your terms inside this array
    $predefined_terms = array(
         'term A'
        ,'term B'
        ,'term C'
    // Name your taxonomy here
    $predefined_taxonomy = 'category';

    $all_terms_inside_tax = get_terms( 
             'hide_empty'   => false
            ,'taxonomy'     => $predefined_taxonomy

    foreach ( $all_terms_inside_tax as $term )
        if ( ! in_array( $term->name, $predefined_terms ) )
            wp_delete_term( $term->term_id, $predefined_taxonomy );
add_action( 'init', 'wpse14350_cleanup_taxonomy_terms' );
share|improve this answer
I like this, this will work just fine. Thanks! – Drew Gourley Apr 9 '11 at 13:20
This would still offer users the add tag form. Not the ideal interaction design. – toscho Apr 9 '11 at 14:08
I'm just going to manually unset the submenu and hide the 'add category' stuff with css, which is an OK solution for my needs. Also, firing this on 'init' is too early, get_terms returns an error, but if you hook it into admin_head it works like a charm. – Drew Gourley Apr 9 '11 at 15:41
@toscho - feel free to modify my answer or add anything to it. Btw: As stated in the headline, it's just a basic concept. – kaiser Apr 9 '11 at 16:13

If you're adding terms into the taxonomy independantly and you want to hide the UI, why not simply use two of register_taxonomy's supported arguments.

(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'

(boolean) (optional) Whether to generate a default UI for managing this taxonomy.

Default: if not set, defaults to value of public argument

Set the capabilities to some nonexistent capabilities and you'll essentially prevent users from being able to modify, create or delete them. If you need to be able to assign them to posts the traditional way(ie. via the post editor), simply use a real capability for the assign_terms value.


$args = array(


    'capabilities' => array(
        'manage_terms' => 'foobar',
        'edit_terms'   => 'foobar',
        'delete_terms' => 'foobar',
        'assign_terms' => 'foobar' // <-- change this one to a desired cap if you need to be able to assign them(you could use manage_options for admins only)

Set show_ui to false and you'll prevent any menu items being shown for the taxonomy.

Hope that helps...

share|improve this answer
I'll add this into my solution as well, may as well use both measures of protection. – Drew Gourley Apr 9 '11 at 23:54

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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