Dorokhov.codes
21. Taxonomies and terms
In WordPress, taxonomies are a way to organize and group content. They help structure content by classifying posts, pages, and custom post types. WordPress has two built-in taxonomies and allows the creation of custom taxonomies.
1. Built-in Taxonomies
WordPress comes with two default taxonomies:
- Categories (
category
) – A hierarchical taxonomy used to group posts into broad topics. A post can belong to multiple categories. - Tags (
post_tag
) – A non-hierarchical taxonomy that allows freeform labeling of posts. Unlike categories, tags do not have a parent-child structure.
2. Custom Taxonomies
Developers can create custom taxonomies to better organize custom post types. These can be:
- Hierarchical – Like categories, allowing parent-child relationships.
- Non-hierarchical – Like tags, with no parent-child structure.
3. Registering a Custom Taxonomy
Custom taxonomies are registered using register_taxonomy()
. Example:
function custom_taxonomy() {
register_taxonomy(
'genre', // Taxonomy slug
'book', // Post type
array(
'label' => __('Genre'),
'rewrite' => array('slug' => 'genre'),
'hierarchical' => true, // True for categories, false for tags
)
);
}
add_action('init', 'custom_taxonomy');
This code creates a “Genre” taxonomy for a custom post type “Book”.
4. Displaying Taxonomies
To display taxonomy terms in a template:
$terms = get_the_terms(get_the_ID(), 'genre');
if ($terms && !is_wp_error($terms)) {
foreach ($terms as $term) {
echo $term->name . ' ';
}
}
5. Querying Posts by Taxonomy
You can retrieve posts based on taxonomy using WP_Query
:
$args = array(
'post_type' => 'book',
'tax_query' => array(
array(
'taxonomy' => 'genre',
'field' => 'slug',
'terms' => 'fiction',
),
),
);
$query = new WP_Query($args);
Database structure
In WordPress, taxonomies and their terms are stored in multiple database tables. Here’s how they are structured:
1. wp_terms
(Stores Term Names)
This table holds the actual terms (categories, tags, or custom taxonomy terms).
term_id | name | slug | term_group |
---|---|---|---|
1 | Fiction | fiction | 0 |
2 | Non-fiction | non-fiction | 0 |
term_id
→ Unique ID for the term.name
→ The term’s human-readable name.slug
→ URL-friendly version of the term.term_group
→ Used for grouping terms (rarely used).
2. wp_term_taxonomy
(Links Terms to Taxonomies)
This table defines which taxonomy a term belongs to.
term_taxonomy_id | term_id | taxonomy | description | parent | count |
---|---|---|---|---|---|
1 | 1 | genre | Fiction books | 0 | 5 |
2 | 2 | genre | Non-fiction books | 0 | 3 |
term_taxonomy_id
→ Unique ID linking terms to taxonomies.term_id
→ Referenceswp_terms.term_id
.taxonomy
→ Name of the taxonomy (e.g.,category
,post_tag
, or custom likegenre
).description
→ Description of the term.parent
→ Parent term ID (for hierarchical taxonomies).count
→ Number of posts associated with this term.
3. wp_term_relationships
(Links Terms to Posts)
This table connects taxonomy terms to posts (or custom post types).
object_id | term_taxonomy_id | term_order |
---|---|---|
101 | 1 | 0 |
102 | 2 | 0 |
object_id
→ The ID of the post (fromwp_posts.ID
).term_taxonomy_id
→ Links towp_term_taxonomy.term_taxonomy_id
.term_order
→ Controls order (not commonly used).
4. wp_termmeta
(Stores Term Metadata)
Introduced in WordPress 4.4, this table stores custom metadata for terms.
meta_id | term_id | meta_key | meta_value |
---|---|---|---|
1 | 1 | color | red |
2 | 2 | icon | book |
meta_id
→ Unique ID for the metadata entry.term_id
→ Referenceswp_terms.term_id
.meta_key
→ Name of the metadata field.meta_value
→ Value of the metadata field.
How Taxonomy Queries Work
When WordPress queries posts by taxonomy, it joins these tables:
- Find the term ID in
wp_terms
. - Get the taxonomy from
wp_term_taxonomy
usingterm_id
. - Retrieve posts from
wp_term_relationships
usingterm_taxonomy_id
.
Example SQL query:
SELECT p.* FROM wp_posts p
JOIN wp_term_relationships tr ON p.ID = tr.object_id
JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms t ON tt.term_id = t.term_id
WHERE tt.taxonomy = 'genre' AND t.slug = 'fiction';