Brush Up Your
Taxonomy Skills

A talk by @thorstenfrommen

What is a Taxonomy?

In WordPress, a taxonomy is a grouping mechanism for some posts.

The names for the different groupings in a taxonomy are called terms.

WordPress Codex

Where to Find
Taxonomies and Terms?

Admin: Edit Terms

Admin: Assign Terms

Front End: Term Archive

How to Use Taxonomies
Programmatically?

Taxonomy Functions


register_taxonomy( $taxonomy, $object_type, $args );

if ( is_tax( $taxonomy, $term ) ) { ... }

if ( is_object_in_taxonomy( $object_type, $taxonomy ) ) { ... }

if ( has_term( $term, $taxonomy, $post ) ) { ... }

wp_set_object_terms( $object_id, $terms, $taxonomy );

$terms = get_terms( $taxonomy, $args );

$objects = get_objects_in_term( $term, $taxonomy, $args );

Tax Query


$posts = get_posts( array(
    'post_type' => 'post',
    'tax_query' => array(
        'relation' => 'OR',
        array(
            'taxonomy' => 'category',
            'field'    => 'slug',
            'terms'    => array( 'wordcamp-berlin' ),
        ),
        array(
            'taxonomy' => 'tag',
            'field'    => 'slug',
            'terms'    => array( 'wcber' ),
        ),
    ),
) );

Actions and Filters


add_action( 'registered_taxonomy', function ( $taxonomy, $object_type ) {
    // ...
}, 10, 2 );

add_action( 'created_term', function ( $term_id, $tt_id, $taxonomy ) {
    // ...
}, 10, 3 );

add_filter( 'get_term', function ( $term, $taxonomy ) {
    // ...
}, 10, 2 );

Taxonomies for Comments

Comment Taxonomies

  • Must be separate taxonomies:
    • separate DB tables for posts and comments;
    • assign term to comment with ID 1
      → also assigned to post with ID 1.
  • Use cases:
    • type (e.g., bug, enhancement, feature request);
    • urgency (e.g., low, moderate, high);
    • ...

Taxonomies for Users

User Taxonomies

  • As with comment taxonomies, must be separate taxonomies.
  • User taxonomies, in general, more useful than comment taxonomies.
  • Use cases:
    • department (e.g., design, development, project management);
    • interest (e.g., diving, music, programming);
    • skill (e.g., back-end development, front-end development, testing);
    • ...

Plugin: User Taxonomies

  • Register a user taxonomy just like you do for post types.

register_taxonomy( $taxonomy, 'user', array(
    // other arguments...

    'rewrite'      => false,
    'capabilities' => array(
        'manage_terms' => 'edit_users',
        'edit_terms'   => 'edit_users',
        'delete_terms' => 'edit_users',
        'assign_terms' => 'read',
    ),

    // other arguments...

Plugin: User Taxonomies


    // other arguments...

    'options' => array(
        'cardinality' => 3,
        'allow_empty' => true,
        'tags'        => true,
        'priorities'  => true,
    ),

    // other arguments...
) );

Plugin: User Taxonomies

Plugin: User Taxonomies

Link Taxonomies,
and Synchronize Their Terms

Linked Taxonomies

  • Two (or more) taxonomies that share the same terms:
    • taxonomies registered for different sets of post types;
    • taxonomies registered for different object types;
    • one visible source taxonomy linked to one or more hidden target taxonomies.
  • Propagate changes to one taxonomy's terms to all linked taxonomies.

Linked Taxonomies

  • Somehow manage linked taxonomies:
    • Which taxonomies are linked to each other?
    • Are there uni- or bidirectional relationships?
  • Hook into relevant actions:
    • created_term;
    • edit_terms;
    • edited_term_taxonomy;
    • delete_term.

Plugin: Linked Taxonomies

Excursus: Metadata

Metadata, by its very definition, is information about information. In the case of WordPress, it's information associated with content in the comments, posts, or users table.

WordPress Plugin Handbook

Metadata Examples

  • Post metadata:
    • _edit_lock;
    • _menu_item_object_id;
    • _wp_page_template;
    • ...
  • User metadata:
    • admin_color;
    • first_name;
    • meta-box-order_post;
    • ...

Metadata Functions


$admin_color = get_user_meta( $user_id, 'admin_color', true );

$related_posts = get_post_meta( $post_id, 'related_post' );

update_user_meta( $user_id, 'show_admin_bar_front', false );

delete_post_meta( $post_id, 'deprecated' );

Meta Queries


$full_width_pages = get_posts( array(
    'meta_key'   => '_wp_page_template',
    'meta_value' => 'templates/full-width.php',
) );

$jane_does = get_users( array(
    'meta_query' => array(
        array(
            'key'   => 'first_name',
            'value' => 'Jane',
        ),
        array(
            'key'   => 'last_name',
            'value' => 'Doe',
        ),
    ),
) );

Performance of Meta Queries

  • Metadata tables are not designed to get queried against by meta value:
    • there is no index on the meta_value column;
    • there is an index on the column holding the related object's ID;
    • also, the (start of the) meta key is indexed.
  • Query against metadata tables by
    • object ID: great, that's how it's supposed to be;
    • object ID and meta key: also great;
    • meta key: perfectly doable.

“But I really DO have to
query by meta value!?„

Meta Terms
to the Rescue!

Meta Taxonomy

  • Use a separate taxonomy to store meta information:
    • use WP_Tax_Query instead of WP_Meta_Query;
    • hierarchical taxonomy for more complex conditions;
    • it's fast!
  • Clearly, this is not possible with every metadata query.

Meta Tax Query


$popular_posts = get_posts( array(
    'post_type'      => 'post',
    'tax_query'      => array(
        array(
            'taxonomy' => 'meta',
            'field'    => 'slug',
            'terms'    => array( 'popular-post' ),
        ),
    ),
    'orderby'        => 'rand',
    'posts_per_page' => 10,
) );

The Best of Both Worlds


$w_org_users = get_users( array(
    'number'    => -1,
    'tax_query' => array(
        array(
            'taxonomy' => 'user_meta',
            'field'    => 'slug',
            'terms'    => array( 'has_w_org_account' ),
        ),
    ),
) );
if ( $w_org_users ) : ?>
<ul>
<?php foreach ( $w_org_users as $user ) : ?>
    <li><?php echo get_user_meta( $user->ID, 'w_org_user', true ); ?></li>
<?php endforeach; ?>
</ul>
<?php endif;

Plugin: Meta Taxonomy

  • Very simple plugin to get you started:
    • registers a post meta taxonomy with (hopefully) appropriate arguments;
    • can be heavily customized by filters (e.g., to work with comments or users).
  • Comes with a function to check if a given object has a given meta term.

if ( has_meta_term( $object_id, $meta_term_id_or_slug ) ) {
    echo 'Yatta!';
}

Latest News

The WP_Term Class

  • Since WordPress 4.4.
  • Replaces old stdClass objects.
  • Static instance getter.
  • Public properties, just like before.

$term = WP_Term::get_instance( $term_id );
if ( $term && 'wordcamp' === $term->taxonomy ) {
    echo $term->name;
}

$new_term = new WP_Term( (object) array(
    'name' => 'New term in the wild',
) );

Term Meta

Not to be confused with meta terms. (ツ)

  • Since WordPress 4.4.
  • Complete metadata support for terms:
    • separate {$table_prefix}_termmeta table;
    • *_term_meta() functions;
    • meta_query parameters for term getters.
  • Use cases:
    • term image;
    • related terms;
    • ...

Thanks!

@thorstenfrommen

slides.tfrommen.de/taxonomy/