Wordpress Query overriding default AND operator - wordpress

I have a wordpress query that is not-using a meta key and needs to override the default AND to an OR
Code snippet:
$args = array(
'post_type' => 'post',
'author__in' => $follow_authors,
'tag_slug__in' => $follows
);
The output statement is ...WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (71) ) AND wp_posts.post_author IN (3)...
I can't find a way to make the ..) AND wp.posts.post_author... to be an OR

Something like this should get you started:
$meta_query_args = array(
'relation' => 'OR', // Optional, defaults to "AND"
array(
'key' => '_my_custom_key',
'value' => 'Value I am looking for',
'compare' => '='
)
);
$meta_query = new WP_Meta_Query( $meta_query_args );
There is more in-depth explanation and examples here: https://codex.wordpress.org/Class_Reference/WP_Meta_Query

Related

Why get_posts() return empty data?

I'm trying to get posts of some type matching a meta query, but whatever I try, I get empty results.
I have
$meta_query = array(
'relation' => 'OR',
array(
'key' => '_wpm_gtin_code',
'compare' => 'EXISTS'
),
array(
'key' => '_product_code',
'compare' => 'EXISTS'
)
);
$args = array(
'meta_query' => $meta_query,
'post_type' => 'product',
'post_status' => 'publish'
//'posts_per_page' => -1
);
error_log(print_r($args, true));
$posts = get_posts( $args );
error_log(print_r($posts, true));
and I see in log file
[02-Mar-2020 06:51:12 UTC] Array
(
[meta_query] => Array
(
[relation] => OR
[0] => Array
(
[key] => _wpm_gtin_code
[compare] => EXISTS
)
[1] => Array
(
[key] => _product_code
[compare] => EXISTS
)
)
[post_type] => product
[post_status] => publish
)
[02-Mar-2020 06:51:12 UTC] Array
(
)
When I select the data manually with this SQL query:
SELECT * FROM wp_posts
INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id )
WHERE wp_posts.post_type = 'product' AND wp_posts.post_status = 'publish' AND
(wp_postmeta.meta_key = '_wpm_gtin_code' OR wp_postmeta.meta_key = '_product_code')
I get correct result of two rows.
What am I doing wrong?
$meta_query = array(
'relation' => 'OR',
array(
'key' => '_wpm_gtin_code',
'compare' => 'EXISTS',
'value' => '' // This is ignored, but is necessary...
),
array(
'key' => '_product_code',
'compare' => 'EXISTS',
'value' => '' // This is ignored, but is necessary...
)
);
$args = array(
'meta_query' => $meta_query,
'post_type' => 'product',
'post_status' => 'publish',
//'posts_per_page' => -1
);
try adding 'value' => '' in array ...
I dived into WP code to find out that the query contained tax_query even I didn't pass any to my get_post() call. So I searched where the query got altered and found that the whole problem was in WooCommerceCategoryExcluder plugin which hooked to pre_get_posts and added taxonomy query to my get_posts() args.
Maybe this investigation helps someone else trying to solve similar problem.

Filter with Advanced Custom Field in WordPress

I am trying to set filters based on Advanced Custom Fields in my WordPress site. Basically my advanced custom field named as 'ispremium' has two values as 'yes' and 'no' and in dropdown filter I have set two options as 'Premium Only' And 'All Programs'.
I need to do when 'Premium Only' dropdown option is selected it will list all the post having value 'ispremium'='yes' and when all program is selected it will list both 'ispremium=yes' and 'ispremium='no'. I have following code but it is listing post with 'ispremium=yes' always. What's wrong in my code?
<select name="order" onchange="this.form.submit();">
<?php
$order_options = array(
'yes' => 'Premium Only',
'no' => 'All Programs',
);
$result = query_posts( array(
'post_type' => 'post',
'meta_query' => array(
array(
'key' => 'ispremium',
'value' => 'yes',
),
) ) );
$result = query_posts( array(
'post_type' => 'post',
'meta_query' => array(
array(
'key' => 'ispremium',
'value' => 'yes','no'
),
) ) );
foreach( $order_options as $result => $label ) {
echo "<option ".selected( $_GET['value'], $value )." value='$value'>$label</option>";
}
?>
</select>
First, try to use WP_Query instead of query_posts(). You also have some syntax errors like 'value' => 'yes','no'.
For premium only:
$args = array(
'post_type' => 'post',
'meta_query' => array(
array(
'key' => 'ispremium',
'value' => 'yes',
'compare' => '='
)
)
);
$the_query = new WP_Query( $args );
All Programs
$args = array(
'post_type' => 'post',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'ispremium',
'value' => 'yes',
'compare' => '='
),
array(
'key' => 'ispremium',
'value' => 'no',
'compare' => '='
)
)
);
$the_query = new WP_Query( $args );
Check ACF documentation for further info. Also, I suggest you to do this with Ajax, since if you put this code within your select element, the available options are going to be the from the last query made, and won't be dynamic on field change.
But I don't totally get what you're trying to do though; you'll probably want to show the available programs in another drop down, or you could simply redirect to another archive page which lists the programs accordingly to the selected option.

Comparing a field with several values at once using meta_query (WP)

I'm comparing the trip_region custom field of my trip CPT to the first element of an array: $filter_region[0].
Howevere I may have more elements in that array and I need to select trips whose trip_region field equals any of these elements. Is it possible, with meta_query, to compare (with an OR, not an AND) a field to several values at once? Because there's nothing quite like that in the doc.
$get_trips_region = get_posts(array(
'post_type' => 'trip',
'meta_query' => array(
array(
'key' => 'trip_region',
'value' => '"' . $filter_region[0] . '"',
'compare' => 'LIKE'
)
)
));
EDIT:
Here's my new code, presumably closer to the solution but doesn't return any result:
$get_trips_region = get_posts(array(
'post_type' => 'trip',
'meta_query' => array(
array(
'key' => 'trip_region',
'value' => $filter_region,
'compare' => 'IN'
)
)
));
EDIT(2):
Replacing get_posts with WP_Query and using WP_Query's request property I see the following SQL query is being executed here:
SELECT SQL_CALC_FOUND_ROWS wp_15_posts.ID FROM wp_15_posts INNER JOIN wp_15_postmeta ON (wp_15_posts.ID = wp_15_postmeta.post_id) WHERE 1=1 AND wp_15_posts.post_type = 'trip' AND (wp_15_posts.post_status = 'publish' OR wp_15_posts.post_status = 'private') AND ( (wp_15_postmeta.meta_key = 'trip_region' AND CAST(wp_15_postmeta.meta_value AS CHAR) IN ('47','46','45')) ) GROUP BY wp_15_posts.ID ORDER BY wp_15_posts.post_date DESC LIMIT 0, 10
Relevant passage I guess is: (wp_15_postmeta.meta_key = 'trip_region' AND CAST(wp_15_postmeta.meta_value AS CHAR) IN ('47','46','45'))
Looks good to me, I don't understand why it doesn't work.
I think you have to compare with IN instead of LIKE. The value must contain an array then. Here's the doc.
$filter_region = array( 'Region 1', 'Region 2' );
$get_trips_region = get_posts(array(
'post_type' => 'trip',
'meta_query' => array(
array(
'key' => 'trip_region',
'value' => $filter_region,
'compare' => 'IN'
)
)
));
You can use compare. Here is another WordPress Codex doc on Meta_Query.

Wordpress WP_Query wildcard in "key"

I've got a simple question yet I cannot find the answer from looking on the web.
With WP_Query, how is the "key" value from a "meta_query" treated? Can I use a wildcard?
For instance:
$args = array(
'post-type' => 'post',
'meta_query' => array(
array(
'key' => 'dates_%_participants',
'compare' => 'LIKE',
'value' => '"'.$user->ID.'"',
)
)
);
$query = new WP_Query($args);
Notice the "%" in the 'key'
Add a filter to the query to replace
meta_key = 'dates_$
with
meta_key LIKE 'dates_%
In functions.php:
function posts_where_dates( $where ) {
$where = str_replace("meta_key = 'dates_$", "meta_key LIKE 'dates_%", $where);
return $where;
}
add_filter( 'posts_where' , 'posts_where_dates' );
Your query remains the same as you had it. ie
$args = array(
'post-type' => 'post',
'meta_query' => array(
array(
'key' => 'dates_$_participants',
'compare' => '=',
'value' => '"'.$user->ID.'"',
)
)
);
Well hidden but documented here: https://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where
Answer was edited due the changed behavior of esc_sql() in WordPress 4.8.3
https://make.wordpress.org/core/2017/10/31/changed-behaviour-of-esc_sql-in-wordpress-4-8-3/

Wordpress WP_Query using filter, custom post types, and custom fields will not return correct post types

I am trying to get results for certain post_types, however, when ever I add the filter to check if the post_title and post_content are "LIKE" the query string, all post_types are returned, including attachment post_types, which I do not want as show in the $args. Here is the code I am trying:
$query_string = get_search_query();
$args = array(
'post_type' => array("hc_pillow", "hc_topper", "hc_accessory", "page"),
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'tab_retail',
'value' => $query_string,
'compare' => 'LIKE'
),
array(
'key' => 'tab_tech',
'value' => $query_string,
'compare' => 'LIKE'
),
array(
'key' => 'tab_shipping_information',
'value' => $query_string,
'compare' => 'LIKE'
)
),
'posts_per_page' => "-1"
);
function filter_where_title($where = '') {
$query_string = get_search_query();
$where .= " OR post_title LIKE '%".$query_string."%' OR post_content LIKE '%".$query_string."%'";
return $where;
}
$posts = new WP_Query();
add_filter('posts_where', 'filter_where_title');
$posts->query($args);
remove_filter('posts_where', 'filter_where_title');
Any help at all would be appreciated, I'm not sure what else to try.,
Your WHERE statement should be structured like that:
WHERE `post_type` IN ( 'hc_pillow', 'hc_topper', 'hc_accessory', 'page' ) AND ( `post_title` LIKE '%search_string%' OR `post_content` LIKE '%search_string%' )
Now it's more like
WHERE `post_type` IN ( 'hc_pillow', 'hc_topper', 'hc_accessory', 'page' ) OR `post_title` LIKE '%search_string%' OR `post_content` LIKE '%search_string%'
where any single condition of the three would be enough to envalidate a row.

Resources