Monday, September 28, 2015

WP_Query Arguments: Taxonomies

So far in this series, you've learned how WP_Query is structured and what its properties and methods are. Now we're looking at the various arguments you can use with WP_Query and how you code them.

WP_Query has a large number of possible arguments, which makes it extremely flexible. As you can use it to query just about anything held in your wp_posts table, it has arguments for every permutation of query you might want to run on your content.

In this tutorial I'll look at arguments for querying taxonomy terms.

A Recap on How Arguments Work in WP_Query

Before we start, let's have a quick recap on how arguments work in WP_Query. When you code WP_Query in your themes or plugins, you need to include four main elements:

  • the arguments for the query, using parameters which will be covered in this tutorial
  • the query itself
  • the loop
  • finishing off: closing if and while tags and resetting post data

In practice this will look something like the following:

The arguments are what tells WordPress what data to fetch from the database and it's those that I'll cover here. So all we're focusing on here is the first part of the code:

As you can see, the arguments are contained in an array. You'll learn how to code them as you work through this tutorial.

Coding Your Arguments

There is a specific way to code the arguments in the array, which is as follows:

You must enclose the parameters and their values in single quotation marks, use => between them, and separate them with a comma. If you get this wrong, WordPress may not add all of your arguments to the query or you may get a white screen.

The Taxonomy Parameters

Setting parameters for taxonomy terms is a little more complicated than for categories and tags since you use tax_query. Within this argument you write a nested array of arguments to specify the taxonomy and term using these parameters:

  • taxonomy (string): Taxonomy.
  • field (string): Select taxonomy term by ('term_id (default), 'name' or 'slug').
  • terms (int/string/array): Taxonomy term(s).
  • include_children (boolean): Whether or not to include children for hierarchical taxonomies. Defaults to true.
  • operator (string): Operator to test. Possible values are 'IN' (default), 'NOT IN', 'AND'.

The fact that you have the operator parameter means you don't need to choose from one of a range of available arguments to define whether you're including or excluding terms (as you do for tags and categories), but use tax_query for everything taxonomy-related instead.

If you want to query for multiple taxonomies, you can also use the relation parameter before all of your arrays (one for each taxonomy) with AND or OR to specify whether you want to find posts with all of the terms or any of them.

This is most easily explained with some examples.

Querying for One Taxonomy Term

This is the simplest scenario and involves just using one nested array:

The above queries for posts with the my-term-slug term in the my-taxonomy taxonomy. Note that you also need to use the field parameter to identify which field you're using to identify the term, unless you're using the term ID which is the default. If you wanted to use the term ID you'd use something like this:

Using the ID makes it harder for you to identify what your query is looking for at a later date, but avoids any potential problems if you think your users might edit the term slugs.

Querying For Multiple Terms in One Taxonomy

If you want to identify posts with one or more of an array of terms in the same taxonomy, you still write one nested array, but add an array of terms.

For example, to query posts with any of a list of term IDs from your taxonomy, you use:

But what if you wanted to query posts with all of these terms? You'll need to use the operator parameter inside your nested array:

Note that the first example actually uses the IN operator to find posts with any of the terms, but as this is the default you don't have to specify it in your arguments.

Another scenario is if you want to query for posts which don't have any of an array of terms in one taxonomy, which you do like this:

Here I've replaced the AND operator with NOT IN, which means WordPress will find posts without any of the terms in the array.

Note that if you prefer to use slugs instead of term IDs, you can do so with any of these scenarios. The last example would look like this:

Another scenario is if you want to query for posts that have one term but not another. This uses the IN operator (which you don't need to include as it's the default), with a minus sign before the ID of any terms you want to exclude:

This queries posts with term 11 but not term 12.

Querying Terms From Multiple Taxonomies

If you want to work with more than one taxonomy, you'll need to create more than one array. Let's look at the simplest example, to query posts with one term from taxonomy1 and one term from taxonomy2:

Here I've written two nested arrays: one for each taxonomy, using the same arguments as I did for the examples using just one taxonomy. I've preceded these with the relation argument. You need to include the relation argument to tell WordPress whether it's looking for all or some of the posts output by each array. This works as follows:

  • If you use 'relation' => 'AND', WordPress will fetch the posts specified in the first array and the second array. So in the example above, only posts with both the slug-one slug in taxonomy1 and the slug-two slug in taxonomy2 will be queried.
  • If you use 'relation' => 'OR', WordPress will fetch posts output by the first array or the second array. So in this case you'll get posts with either the slug-one slug or the slug-two slug (or both).

This is the code you'd use if you were looking for posts with either of the two slugs:

You can also look for more than one term in a given taxonomy by adding it to the array:

By combining the relation argument with nested queries also using the operator argument, you can create quite complex queries. The arguments below would query posts with a term from one taxonomy but without a term from another taxonomy:

Note that I've used 'relation' => 'AND' here: if I used OR, it would query posts with slug-two and posts without slug-one, rather than posts which have slug-two but not slug-one, which is what I'm looking for. 

You could conceivably take this further to query your taxonomies' terms however you wanted: using the operator argument in both nested queries or adding an additional nested query to query terms in another taxonomy.

A Note on the tax Argument

You may be wondering why I haven't included the {tax} argument, where you simply write your argument as follows:

You may be familiar with this way of querying taxonomies if you've done it in the past, but it's now deprecated and you shouldn't use it. So stick to 'tax_query'! Using tax_query gives you a lot more flexibility anyway.

Summary

Querying taxonomies is a bit more complicated than categories and tags, as you need to get to grips with the tax_query argument.

However, as we've seen, this is a very powerful argument that gives you a lot of scope and flexibility to query your database in whatever way you wish.


by Rachel McCollin via Tuts+ Code

No comments:

Post a Comment