#30846 closed defect (bug) (invalid)
Custom query using tag__in sets query_var tag_id
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | Priority: | normal | |
| Severity: | normal | Version: | 4.1 |
| Component: | Taxonomy | Keywords: | |
| Focuses: | Cc: |
Description
When creating a custom query and using the tag__in parameter, WP_Query::get_posts() sets tag_id to the first id in the tag__in array. This renders the tag__in array useless. For example, if the first tag id in the tag__in array has no posts; an empty array is returned.
To recreate:
- Create 3 or more tags (in my example, I'll refer to them as "A" with ID 2, "B", with ID 3 and "C" with ID 4.
- Assign posts to "A" and "B", but do NOT assign any posts to "C". (Tag "C" should have no posts associated with it)
- Create a custom query using the
tag__inparameter, like so:
$queryArgs = array(
'tag__in' => array(4,3,2)
);
$query = new WP_Query($queryArgs);
var_dump($query->query_vars);
var_dump($query->get_posts());
- When looping through the query, you'll note that there will be no posts.
- Similarly
$query->get_posts()returns an empty array. $query->query_varswill show thattag__inis set correctly, but thetag_idparameter is also set to the first element in thetag__inarray.
var_dump($query->query_vars) output from the code above
(Irrelevant parts of array removed, denoted by ellipses)
array (size=61)
'tag__in' =>
array (size=3)
0 => int 4
1 => int 3
2 => int 2
'error' => string '' (length=0)
'm' => string '' (length=0)
...
'tag' => string '' (length=0)
'cat' => string '' (length=0)
'tag_id' => int 4
...
'category__in' =>
array (size=0)
empty
'category__not_in' =>
array (size=0)
empty
'category__and' =>
array (size=0)
empty
'post__in' =>
array (size=0)
empty
'post__not_in' =>
array (size=0)
empty
'tag__not_in' =>
array (size=0)
empty
'tag__and' =>
array (size=0)
empty
'tag_slug__in' =>
array (size=0)
empty
'tag_slug__and' =>
array (size=0)
empty
'post_parent__in' =>
array (size=0)
empty
...
Attachments (2)
Change History (8)
#3
@
11 years ago
boonebgorges - Thank you very much for the reply and unit test. It is possible that I'm doing something out of context and that could be causing the issue. If so, I'm sorry in advance for wasting everyone's time!
Setup
- This is a completely clean install with no additional plugins. I am using theme Twenty Fifteen.
- I placed the custom query outlined above on a custom page template; again, so I could isolate the problem. I have attached that file for reference. I created a new page that uses this template and loaded the page.
Unit Test
Thank you for the unit test - it looks like the first assertion in the unit test should cover the issue that I'm seeing because the first tag does not contain any posts. I will install the test suite and verify that the test passes.
Query Issue
It does indeed appear that the term_id (by way of term_taxonomy_id) is getting added to the query, assuming that $query->request is the actual request that fetches the posts. Below is an echo of $query->request. You'll notice that wp_term_relationships.term_taxonomy_id IN (5) is added - and because there are no posts associated with term_taxonomy_id 5, this results in an empty set.
If I remove this from the query (and the subsequent
ANDof course), I get the results I would expect -- all posts associated with 3, 4 and 5.
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) INNER JOIN wp_term_relationships AS tt1 ON (wp_posts.ID = tt1.object_id) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (5) AND tt1.term_taxonomy_id IN (3,4,5) ) AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish') GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 10
I will report back after completing the testing.
#4
@
11 years ago
- Resolution set to invalid
- Status changed from new to closed
Thanks for the unit test - I'll use that in the future. I figured it out.
I was attempting to run $query->get_posts() after instantiating the query. This was what was causing the extra 'AND' in the MySQL query mentioned in my previous remarks.
I assumed that $query->get_posts would not modify the query when run after instantiation, but that doesn't seem to be the case.
#5
@
11 years ago
philbirnie - Aha, thanks for the update. This is the same problem (and solution) as what I described here: https://core.trac.wordpress.org/ticket/27193#comment:10 In short, when you set up a new WP_Query object, the get_posts() method is automatically called internally during the setup process. Invoking that method again can cause the kinds of query_var stomping that you've described here. We ought to have better documentation of this behavior.
philbirnie - Thanks for the detailed report.
You're correct that
tag_idgets set to the first member oftag__in. This happens primarily for backward compatibility, to ensure that thetag_idquery var is always backfilled when viewing a taxonomy archive, in case themes attempt to reference it directly when (eg) setting up page titles. However, it's not referenced when building the SQL query itself.WP_Queryconverts all the query_vars passed directly to the class into a single unifiedtax_query; see https://core.trac.wordpress.org/browser/trunk/src/wp-includes/query.php#L1951. This tax query correctly recognizes thetag__inparam. Thetag_idbackfilling happens afterward: https://core.trac.wordpress.org/browser/trunk/src/wp-includes/query.php#L2709The attached unit test 30846.test.diff shows that this is working properly. Can you look at the logic there to make sure I'm understanding your report correctly?
Double check to make sure you don't have any plugins or other customizations doing anything odd here. If you continue to have the problem even without any plugins, please share more detail about exactly *where* you're generating the query - the only possibility I can see is that there's something funny going on where you're trying to do a taxonomy-related query while on a single term's taxonomy archive page, or something like that.