23.6 Disabling Taxonomies
Right, so you’ve built this beautiful taxonomy system. Categories for your broad sections, tags for the free-form chaos, maybe even a custom taxonomy for ‘Pizza Toppings’ because why not. But now, you’ve hit a point where you need to perform a bit of taxonomy-ectomy. Maybe the client decided ‘Tags’ are too 2009, or perhaps that custom ‘Manufacturer’ taxonomy you built is now being handled by a separate plugin that’s throwing a fit. Whatever the reason, you need to disable a taxonomy, not just hide it.
Here’s the thing WordPress doesn’t shout from the rooftops: once a taxonomy is registered, it’s in the database. Disabling it in code doesn’t make those terms vanish into the ether. It just tells WordPress to stop adding to the pile and to stop showing the UI for it. The existing terms are still there, sitting in the wp_terms table, holding hands with their post relationships in wp_term_relationships. This is actually a good thing—it means if you accidentally disable the wrong thing, no data is lost. We’re just turning off the lights and locking the door; the furniture inside remains.
The 'show_ui' vs. 'public' Misdirection
Your first instinct might be to set 'public' => false in your register_taxonomy() args. Don’t. Well, you can, but it’s a blunt instrument. Setting 'public' => false also makes the taxonomy’s permalinks and archive pages inaccessible, which is often overkill. What you usually want is to kill the UI—the meta boxes and the admin menu items—while leaving the underlying structure intact for any code that might still be using it. For that, you want the precision strike of 'show_ui' => false.
Let’s say you want to disable the standard Tags taxonomy. You have to re-register it with your new arguments. The init hook is your friend here, but you need to ensure you do it after WordPress’s own registration, hence a slightly higher priority.
<?php
// This goes in your theme's functions.php or a plugin file.
add_action( 'init', 'wp_docs_disable_tags_ui', 99 ); // Late to the party
function wp_docs_disable_tags_ui() {
// Get the existing taxonomy object to not lose all its settings
$taxonomy = get_taxonomy( 'post_tag' );
// Check if it exists so we don't cause a fatal error
if ( $taxonomy ) {
// Re-register it, but flip the UI off
register_taxonomy(
'post_tag',
$taxonomy->object_type, // Keep its original post types
array(
'label' => $taxonomy->label,
'public' => $taxonomy->public,
'show_ui' => false, // <- This is the magic button
'show_in_nav_menus' => false, // Also boot it from menus
'show_admin_column' => false, // And from the post list table
'rewrite' => $taxonomy->rewrite,
// ... copy any other args you need to maintain
)
);
}
}
This code effectively removes the Tags meta box from the post editing screen and the “Tags” menu item from the admin sidebar. The tags themselves are still assigned to posts and can be queried; you just can’t manage them through the admin anymore.
Disabling a Custom Taxonomy You Control
If it’s a taxonomy you built yourself, you have two choices. The “nuke it from orbit” option is to simply remove the register_taxonomy() call entirely. This is the equivalent of setting 'public' => false and 'show_ui' => false. The taxonomy will vanish from the UI and its archives will return 404s. The data, again, remains.
The more surgical option is to modify your existing registration code. Find where you registered it and change the arguments.
// From this:
$args = array(
'public' => true,
'show_ui' => true,
// ... other args
);
// To this:
$args = array(
'public' => true, // Archives remain accessible
'show_ui' => false, // UI is removed
// ... other args
);
register_taxonomy( 'pizza_toppings', 'post', $args );
The “Why Won’t It Go Away?!” Pitfall
The most common headache here is cache. WordPress object cache, your browser cache, your opcode cache (like OPCache), you name it. You’ve just changed the registration arguments, but the old admin menu might still be staring back at you. Always clear any server-side caching and do a hard refresh (Ctrl+F5 or Cmd+Shift+R) in your browser after making these changes. If it’s still there, double-check your hook priority. Using a priority of 99 is a good way to ensure your code runs after most others, including WordPress’s core registrations.
Remember, disabling is not deleting. It’s a way to tidy up the interface and prevent future use without committing to the terrifying finality of wp_delete_term(). It’s the technical equivalent of putting something in the attic instead of taking it to the dump.