So, I need to run a Tax query inside a Meta query clause. This does not seem to be possible with the ‘meta_query’ argument, something like this:
Correct, what you want to do is not possible using the parameters of WP_Query
while keeping your data stored as is. The query is already very expensive/slow to run, and if you could add in the taxonomy term query it would be even more expensive.
Instead, these values should never have been stored as post meta, they should have been stored as taxonomy terms. You can do this with a private/hidden taxonomy, and ACF can be told to use that taxonomy to store the values.
For example, a show_in
taxonomy with terms such as on_tour
or is_creation
.
You can then test for this using a standard tax_query
clause. You can also create secondary terms such as not_on_tour
, allowing you to take the super expensive NOT IN
queries and replace them with super cheap/fast versions.
Additionally, you can test using has_term
, e.g.:
// should we show this post on the homepage?
if ( has_term( [ 'homepage' ], 'show_on' ) {
//
}
This is significantly faster to query for than post meta, and on large sites this can be thousands of times faster to query for.
You can also automate some of this, e.g. on a lot of sites I’ve been involved with, a show_on_homepage
term is added to every single post automatically using the save_post
hook. The user can then remove that term and replace it with a hide_on_homepage
term. This is also a great way to let users curate regions or zones of prominent pages, like a show_in_homepage_carousel
term.
All that’s needed to support this on the homepage, is a custom taxonomy named something like hidden_post_markers
, and a snippet in functions.php
like this:
add_action( 'pre_get_posts', function( $query ) {
if ( $query->is_home() && $query->is_main_query() ) {
$query->set( 'hidden_post_markers', 'show_on_homepage' );
}
} );
As a general guide:
- If you need to find a post or query for posts by a piece of data, that data should be represented as a term in a taxonomy
- If a piece of data about a post is only accessed when you already know the post ID, such as when displaying a post, then use post meta
- You can store data in both
- You can store a simplified version in terms for querying, and a more detailed version in post meta for display
- You can store boolean data as terms, the simplistic method is to create two terms with
_true
and_false
appended to the names, or just testing for the presence of the term - The post meta table wasn’t designed for searching for posts, expect major performance issues
- The taxonomy/term system was designed for searching for posts, filtering them in queries, etc.
meta_query
queries get more expensive as the number of posts rises, and it gets expensive/slow fast