Saw a post over on the WordPress Stack Exchange site a while back, and though I sorta went into it in my answer there, I figured it would make a decent topic.
Custom taxonomies are great. But they’re not great for everything. When designing a custom solution, it’s helpful to understand this in advance, so you can choose what goes where properly.
What is a Taxonomy?
According to Wikipedia, Taxonomy is the practice and science of classification. I like this definition a lot, because it really points out what you’re doing with taxonomies. You’re classifying things. Or better yet, grouping them.
That word is important: Grouping. You’re putting things into groups. The taxonomy is the sum of those groups.
In the case of WordPress, you’re putting posts into groups. Maybe they’re custom post types of some kind (actually, they probably are if you’re doing it properly), but they still fit into the wp_posts table, so lets call them posts. You’re grouping posts together.
Categories group posts together. Tags group posts together. The way that these two are used is somewhat different, but that’s the basic end result here, right?
The group itself is the important bit. Not the term, the term you use for that group is just a label. It has no real significance whatsoever.
Now, I know that we often display the term, and I think that this is what confuses people. The category or tag is probably a word, in English (or your own language), and words have meaning. So yes, it does matter when I add “php” as a tag, or use the “Rants” category. But what’s important to realize is that that word only has meaning to people, not to the computers, and certainly not to our data design.
Enter Postmeta, Stage Left
Let’s say I’m building a new site, and I want to make, say, television shows be a custom post type. TV Shows are a pretty good choice for this example, as well as what the original SE question was about.
What makes sense as a taxonomy for a TV Show? Title? Actors? Episode numbers? Season numbers? For each item, you need to consider whether it makes more sense as a taxonomy or as pure post meta, or (rarely) both.
Titles makes perfect sense for a taxonomy. You’re grouping all the episodes of that show together, and people will want to see an episode listing. So yes, it’s a taxonomy.
Actors also makes sense as a taxonomy. Actors act in many roles, it would be nice to see what various shows and episodes they’ve been in.
Season and Episode numbers is another one. Every show has it’s own season and episode number. Usually this is represented as Season 1, Episode 1, sort of thing. At first glance, season numbers kinda makes sense as a taxonomy, since you can pull all of season 1 out. But on further reflection, no it doesn’t, because it doesn’t stand alone. Every TV series has a season 1. We don’t want to pull out all season 1 shows from all series, it’s not something we’ll need to do. Same goes for episode numbers, when are we going to make a query based on episode numbers, to get all the first episodes of all shows? Makes no sense. These should be postmeta (or “Custom Fields” as some people insist on calling them).
The difference is one of grouping. For Titles and Actors, we’re grouping individual things together in a meaningful way that stands alone. Sure, our labels (terms) will have meaning to us humans, but not to the act of the grouping itself. The group is a natural one. For seasons, the grouping is meaningful, but less so because it’s shared among non-similar things (different shows). It doesn’t stand alone. You could get around that by saying that your term would be title-season# or similar, but it really makes more sense as postmeta, since the season and episode number, taken together, are unique to the item we’re storing.
Postmeta as Unique Information
That’s the difference: Postmeta is bits of information that are specific to the post item itself. Taxonomies are bits of information shared, in a meaningful manner, by many different items. Title is shared across all episodes of a TV Show, and defines a meaningful relationship to all those episodes. Season number is shared, but it’s not meaningful because all shows have similar season numbers.
Notably, there’s easy ways to order by postmeta, but not by a taxonomy. Ordering by a taxonomy makes no real sense, because lots of items will share the same terms in that taxonomy. If I have 20 items all with “foo” as a term in a taxonomy, then what am I ordering them by? They’re all “foo” items.
As for querying, I can query based on either postmeta or taxonomy, if I really want to. Ideally, I’d do both. For example, if I wanted Firefly, Season 1, Episode 13, then I could specify both a tax_query for title and a meta_query for “S01E13” and get that one unique item. If I wanted all episodes of it in order, then I specify the tax_query for title and the meta query to select the season/episode metadata, then use the orderby to put them in the right order.
So if I can query by them both, but only order by postmeta, then what’s the difference? Why not use postmeta for everything?
Speed. Querying for a taxonomy is loads faster than querying for posts with certain meta information. Even better, I can use both to make things even speedier. The meta_query for S01E13 is going to be loads faster when I specify that title taxonomy, because now it’s only looking for S01E13 amongst Firefly episodes, not amongst all episodes of all shows.
The bottom line is that it’s best to use a taxonomy for attributes that a) define a natural grouping of your items, and b) which are natural labels and not inherently useful data to your methods. The title is not inherently a useful data (it’s just text, could be anything), but the episode number is a number which you will want to order by and display/change/set. You use that episode number for doing something.
Also, it’s perfectly understandable for individuals to disagree on any given example. There is no “right” answer, there’s only the answer that satisfies your own personal use cases. When designing your taxonomies, just remember to think about grouping of items and how you’re going to use the data you’re defining. If it’s a group in how you are going to use it, then a taxonomy works better than postmeta. But if you need the attribute to be manipulated in some manner, then a postmeta works better.