I’m not sure if this is a bug, but it need further investigation. I’ve run a few quick tests on the name
field in a tax_query
, and whenever a term name has got a special character or have more than one word, the tax_query
is excluded from the SQL query
TEST 1
I have use two terms here, your term Ski-in/Ski-out
and one of the terms on my test site Uit die koskas
. Now, if I run my custom query as follows
$taxQuery = new \WP_Query(array(
'post_type' => 'post',
'tax_query' => array(
array(
'taxonomy' => 'category',
'field' => 'name',
'terms' => 'Ski-in/Ski-out',
'operator' => 'IN'
)
)
));
?><pre><?php var_dump($taxQuery->request); ?></pre><?php
the var_dump()
of the request gives me this
string(254) "SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
WHERE 1=1
AND (
0 = 1
)
AND wp_posts.post_type="post"
AND (wp_posts.post_status="publish"
OR wp_posts.post_status="private")
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 4"
The tax_query
is not appended to the SQL query
TEST 2
If you take a single word term with no special character, the query works. Here I’ve tested with a term called Ongekategoriseerd
$taxQuery = new \WP_Query(array(
'post_type' => 'post',
'tax_query' => array(
array(
'taxonomy' => 'category',
'field' => 'name',
'terms' => 'Ongekategoriseerd',
'operator' => 'IN'
)
)
));
?><pre><?php var_dump($taxQuery->request); ?></pre><?php
This gives me the correct SQL query
string(378) "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)
WHERE 1=1
AND (
wp_term_relationships.term_taxonomy_id
IN (1)
)
AND wp_posts.post_type="post"
AND (wp_posts.post_status="publish"
OR wp_posts.post_status="private")
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 4"
I’m not yet sure if this is intentional or a bug, but in the meantime you can have a look at the WP_Query
source code and see how the tax_query
is build. I will look into it as well in the near future
UPDATE 1
I quickly had a look through the WP_Query
class before leaving for work. Towards the end of the class, WP_Query
does some backward compatibility tests, and from eye value it might seem that this is where everything fails which in turn fails in appending the join clausse to the SQL query.
I cannot find a trac ticket about this issue, if there are one and anyone has a link, feel free to update my answer or post in comments.
WORKAROUND
If you need to and have to use the term name, you should create yourself a helper function using get_term_by()
. You can then use the term name to get the term object and use the term ID from there to use in a tax_query
UPDATE 2
FOUND IT
The problem was not in WP_Query
itself (what a mess looking through these classes). WP_Query
uses WP_Tax_Query
to construct the tax_query
. Check the last line just before the do_action
call in the parse_tax_query
method in WP_Query
$this->tax_query = new WP_Tax_Query( $tax_query );
Great, moving to the WP_Tax_Query
class. This class have the following method, transform_query
which transforms a single query from one field to another. This is where everything breaks when you set your field
parameter to name
With the field
set to name
, the name is sanitized using sanitize_title_for_query
$terms = "'" . implode( "','", array_map( 'sanitize_title_for_query', $query['terms'] ) ) . "'";
This removes slashes and convert empty spaces into hypens. This means Ski-in/Ski-out
is converted into ski-inski-out
and Uit die koskas
is converted to uit-die-koskas
. Because your term name is invalid, the following query which gets the term id and its children,
$terms = $wpdb->get_col( "
SELECT $wpdb->term_taxonomy.$resulting_field
FROM $wpdb->term_taxonomy
INNER JOIN $wpdb->terms USING (term_id)
WHERE taxonomy = '{$query['taxonomy']}'
AND $wpdb->terms.{$query['field']} IN ($terms)
" );
fails and returns an empty array
array(0) {
}
CONCLUSION
IMHO, the sanitation here is wrong and should be replaced with a more appropriate method which allows for single spaces and slashes. What is purpose of having a name
field if you can’t use term names properly. This sanitation kills the usage of the name
field in a tax_query
in the above mentioned cases.
As I already stated before, maybe the best method if you need to use term names is to create that helper function where you use get_term_by()
to get the ID from a term and then use that ID in your tax_query
UPDATE 3
Thanks to @manifestphil in comments, there is a changeset #31346 out on this exact crazy over-sanitizing issue. Lets hope this get fixed in future releases