I’m currently running WordPress on version 4.6.1 and I’m attempting to search for posts that contains the character -
(hyphen). However, the search parameter is taking my hyphen for a negation.
From the WP_Query documentation:
Prepending a term with a hyphen will exclude posts matching that term. Eg, ‘pillow -sofa’ will return posts containing ‘pillow’ but not ‘sofa’ (available since Version 4.4).
Here’s my query:
$query = new WP_Query(array(
'post_type' => array('product', 'product_variation'),
's' => '-',
'posts_per_page' => 36
));
I’ve tried to escape the hyphen by doing:
's' => '\-'
However, the result stays the same (var_dump($query->request)
):
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
WHERE
1=1
AND (((wp_posts.post_title NOT LIKE '%%')
AND (wp_posts.post_excerpt NOT LIKE '%%')
AND (wp_posts.post_content NOT LIKE '%%')))
AND (wp_posts.post_password = '')
AND wp_posts.post_type IN ('product', 'product_variation')
AND (wp_posts.post_status="publish" OR wp_posts.post_status="acf-disabled")
ORDER BY
wp_posts.post_date DESC
LIMIT 0, 36
One approach is to modify the exclusion prefix through the wp_query_search_exclusion_prefix
filter that’s supported in WP 4.7+.
See ticket #38099.
Here’s an example how we can change it from -
to e.g. !
:
add_filter( 'wp_query_search_exclusion_prefix', function( $prefix )
{
return '!'; // adjust to your needs (default is -)
} );
where we would use !apple
instead of -apple
to exclude apple
from the search results. Then you can search by -
.
It looks like the exclusion prefix must be a single character (or empty to disable this feature), because of this check in the core:
// If there is an $exclusion_prefix, terms prefixed with it should be excluded.
$exclude = $exclusion_prefix && ( $exclusion_prefix === substr( $term, 0, 1 ) );
if ( $exclude ) {
$like_op = 'NOT LIKE';
$andor_op = 'AND';
$term = substr( $term, 1 );
} else {
$like_op = 'LIKE';
$andor_op = 'OR';
}
Otherwise it sounds like a bug, not to be able to search only for the term exclusion prefix.
I wonder if it would be better to add an extra $exclusion_prefix !== $term
check to support that:
$exclude = $exclusion_prefix
&& $exclusion_prefix !== $term
&& ( $exclusion_prefix === mb_substr( $term, 0, 1 ) );
if ( $exclude ) {
$like_op = 'NOT LIKE';
$andor_op = 'AND';
$term = mb_substr( $term, 1 );
} else {
$like_op = 'LIKE';
$andor_op = 'OR';
}
where we would also use mb_substr()
instead of substr()
for a wider char support for the exclusion prefix.
I guess I should just create ticket for this …