“Taxonomy is a practice and science concerned with classification or categorization.” ~ Wikipedia.
A post type defines a type of content, while a taxonomy defines a way to categorize that content. For example, you could have a taxonomy “Genre” for a book post type. Terms are just single options in the taxonomy. For genre, you could have terms like “fantasy”, “sci-fi”, “business”, etc.
The generic post has, by default, 2 taxonomies – category and tag. Category is a hierarchical taxonomy. This means terms can have parent-child relationships. A “Technology” category can have subcategories like “Frontend”, “Backend”, etc. Tag is a non-hierarchical taxonomy. All terms (tags) are on the same level.
Here’s how to register a “Genre” taxonomy for our book post type:
function register_genre_taxonomy() {
$labels = [
'name' => 'Genres',
'singular_name' => 'Genre',
'search_items' => 'Search Genres',
'all_items' => 'All Genres',
'edit_item' => 'Edit Genre',
'update_item' => 'Update Genre',
'add_new_item' => 'Add New Genre',
'new_item_name' => 'New Genre Name',
'menu_name' => 'Genres',
];
$args = [
'labels' => $labels,
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'rewrite' => [ 'slug' => 'genre' ],
];
// 1st arg: The unique taxonomy name.
// 2nd arg: The post type(s) it applies to.
// 3rd arg: The arguments array.
register_taxonomy( 'thm_genre', [ 'thm_book' ], $args );
}
add_action( 'init', 'register_genre_taxonomy' );Just as with custom post types, the list of arguments isn’t exhaustive, RTFM. After this taxonomy is successfully registered, a “Genres” sub-menu will appear under the “Books” tab in the admin panel. You’ll be able to add terms there. Yes, you don’t register terms in code. You create them in the admin panel, just like you would create a post. Then, when editing a “book” post, you’ll see a meta box letting you select the genres you want to assign this book to.
You can also connect an existing taxonomy to a post type. A primary use case is making the built-in category or tag taxonomies available to custom post types. You’d use the register_taxonomy_for_object_type( $taxonomy, $post_type ) function.
Taxonomies In The Database
The way taxonomies and terms are stored in the database is a little complex, but it’s worth understanding. The structure is based on 3 tables: wp_terms, wp_term_taxonomy, and wp_term_relationships.
wp_terms stores all of the terms. This table has only 3 important columns: term_id, name, and slug. It stores no information on the relationships between those terms and taxonomies. If we were to add the term Fantasy to our Genre taxonomy, its name would be stored here along with its ID (which is just an auto increment field).
wp_term_taxonomy connects terms with taxonomies. The 3 most important columns are term_taxonomy_id (auto increment), term_id, and taxonomy. term_id stores the foreign key from wp_terms. It’s the unique ID (term_id) of the term. The taxonomy column stores the name of the taxonomy as registered in code. This would be “thm_genre”.
Keep in mind, no data about the taxonomy itself is stored in the database. It’s all defined in code when WordPress loads (in that case – in our register_genre_taxonomy() function). There’s also a parent column which is used if your taxonomy is hierarchical (like category is) and the term has a parent. It’s the term_taxonomy_id of the parent term (and 0 if the term doesn’t have a parent).
wp_term_relationships is the glue between posts and terms. The only 2 significant columns are object_id and term_taxonomy_id. object_id is the ID of the post (post_id from the wp_posts table). term_taxonomy_id is a foreign key from the wp_term_taxonomy table. It connects the post with the appropriate term.