Wordpress modify meta query - wordpress

I have loop in functions.php with this code:
$meta_query[] = array(
'key' => '$key',
'value' => $value,
'compare' => 'IN',
);
and i trying to add next $meta_query after loop but with "<" in compare. When I add 'IN' it's working but when i change to '>=" or ">" it doesn't work.
$meta_query[] = array(
'key' => 'price',
'value' => $value,
'compare' => '>=',
);
Do you know why?
This is my fullcode:
// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array(
'field_1' => 'type',
'field_2' => 'price',
'field_3' => 'type2',
'field_4' => 'city',
'field_5' => 'price_min',
'field_6' => 'price_max',
);
function my_pre_get_posts( $query ) {
global $post;
global $wpdb;
$parametry = get_field_objects($post->ID);
if(!is_single() && $post->ID != 2 && $query->get( 'cat' )){
/* start filter*/
$meta_query = $query->get('meta_query');
foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
// continue if not found in url
if( empty($_GET[ $name ]) ) {
continue;
}
// get the value for this filter
// eg: http://www.website.com/events?city=melbourne,sydney
$value = explode(',', $_GET[ $name ]);
// append meta query
if($name == 'price_min'){
$meta_query[] = array(
'key' => 'price',
'value' => $value,
'compare' => '>=',
);
}
elseif($name == 'price_max'){
$meta_query[] = array(
'key' => 'price',
'value' => $value,
'compare' => '<=',
);
}
else{
$meta_query[] = array(
'key' => $name,
'value' => $value,
'compare' => 'IN',
);
}
}
// update meta query
$query->set('meta_query', $meta_query);
In URL (and in table wp_postmeta) i have: type, type2, price and city. I don't have price_min and price_max so I want operate on price field.
This is my working array after filtering:
Array ( [0] => Array ( [key] => type [value] => Array ( [0] => flat) [compare] => IN ) [1] => Array ( [key] => city[value] => Array ( [0] => Cracow) [compare] => IN ) )
and this is not working array when I add price_min and price_max:
Array ( [0] => Array ( [key] => type [value] => Array ( [0] => flat) [compare] => IN ) [1] => Array ( [key] => city [value] => Array ( [0] => Cracow) [compare] => IN ) [2] => Array ( [key] => price [value] => Array ( [0] => 50000 ) [compare] => >= ) [3] => Array ( [key] => price [value] => Array ( [0] => 300000 ) [compare] => <= ) )

It's likely that the $value is not an integer so trying to compare the value of it as an integer when it's a string will cause some issues. Before your WP_Query arguments, place this code in your file:
$value = (int) $value;
Take a look at type juggling in PHP for more info.
This is the documentation for WP_Query meta comparisons.

Related

Comparing arrays in WP_Query with custom fields

I'm having an issue with comparing values between two arrays in wp_query
I have the two roles administrator and forhandler_salg ($roles returns an array with these two values), but it only queries posts with the "public" key set to true
I got more posts when I changed the "allowed_userroles" key compare value to "LIKE", but those aren't the right posts
$roles = "";
if (is_user_logged_in()) {
$user = wp_get_current_user();
$roles = (array) $user->roles;
}
$args = array(
'post_type' => 'downloads',
'posts_per_page' => '-1',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'public',
'value' => true,
'compare' => '=',
),
# Not working
array(
'key' => 'allowed_userroles',
'value' => $roles,
'compare' => 'IN',
),
),
);
print_r($args) returns
Array
(
[post_type] => downloads
[posts_per_page] => -1
[meta_query] => Array
(
[relation] => OR
[0] => Array
(
[key] => public
[value] => 1
[compare] => =
)
[1] => Array
(
[key] => allowed_userroles
[value] => Array
(
[16] => administrator
[17] => forhandler_salg
)
[compare] => IN
)
)
)
And a post with the "public" custom field as true and some added roles returns this, when I print_r() the allowed_userroles for the post:
Array
(
[0] => role1
[1] => role2
[2] => role3
)
How would I go about checking if allowed_userroles in the query has values that are also present in $roles?
EDIT: "like" works if I put in a role manually
Ok, for these kinds of problems, it's easier to start with your basic array of arguments and then modify it.
Since this question is tagged with ACF, ACF is likely storing this as a single meta entry. Furthermore, if this is an array of values, ACF is very likely storing it as a serialized PHP string in the database (e.g., a:2:{i:0;s:4:"1234";i:1;s:3:"qed";}).
Let's start with the base code:
$roles = [];
if (is_user_logged_in()) {
$user = wp_get_current_user();
$roles = (array) $user->roles;
}
$args = array(
'post_type' => 'downloads',
'posts_per_page' => -1,
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'public',
'value' => "1",
'compare' => '=',
),
),
);
In this case, you'll need to use a LIKE to attempt a sub-string match.
foreach($roles as $role) {
$args['meta_query'][] = [
'key' => 'allowed_userroles',
'value' => $role, // can't remember if wp will wrap value with %
'compare' => 'LIKE',
];
}
Ideally, you'd want to match based on the string length as well, but that might be a bit prohibitive. If you keep running into issues getting the exact results out, you could run two separate queries. The first query would be for all public items, and the second query would be for non-public items. You could then take the results of the second query and then filter out values that do not have the correct meta, since it'll be easier to process using get_field('allowed_userroles').

How can I filter records in custom post type list in admin based on user_id that passed as a query string parameter

Is there any option that I can further filter post list for a custom post type in admin based on user_id if the same has been passed as a query string like http://album.multibaselocal.com/wp-admin/edit.php?post_type=albums&user_id=31 ?
Here is what I want to accomplish:
I have a custom post type called album which is used by site users to upload Albums to the system. By default when I go to the list page all albums come up fine. In user list page, I have added a custom column which shows a count of Published albums by each user which links back to album list page with a query string user_id like above.
I want to filter the albums by the user_id I have passed. Is this possible?
I am trying this:
add_filter( 'parse_query', 'filter_albums_further_if_user_id_found');
function filter_albums_further_if_user_id_found($query) {
if( isset($_GET['user_id']) && !empty($_GET['user_id'])) {
$user_id = $_GET['user_id'];
$requery = array(
'post_type' => 'albums',
'post_author' => $user_id,
'status' => 'publish',
'posts_per_page' => -1,
);
// What to do here?
}
}
I have lost here completely. Not an experienced WP developer!
If I have not understood it all wrong, because the hook I am using is called parse_query, I have to somehow parse the query again and filter the existing result using user_id. But don't know where and how.
EDIT (Query output):
WP_Query Object
(
[query] => Array
(
[post_type] => albums
[posts_per_page] => 20
)
[query_vars] => Array
(
[post_type] => albums
[posts_per_page] => 20
[error] =>
[m] =>
[p] => 0
[post_parent] =>
[subpost] =>
[subpost_id] =>
[attachment] =>
[attachment_id] => 0
[name] =>
[static] =>
[pagename] =>
[page_id] => 0
[second] =>
[minute] =>
[hour] =>
[day] => 0
[monthnum] => 0
[year] => 0
[w] => 0
[category_name] =>
[tag] =>
[cat] =>
[tag_id] =>
[author] =>
[author_name] =>
[feed] =>
[tb] =>
[paged] => 0
[meta_key] => user_id
[meta_value] => 31
[preview] =>
[s] =>
[sentence] =>
[title] =>
[fields] =>
[menu_order] =>
[embed] =>
[category__in] => Array
(
)
[category__not_in] => Array
(
)
[category__and] => Array
(
)
[post__in] => Array
(
)
[post__not_in] => Array
(
)
[post_name__in] => Array
(
)
[tag__in] => Array
(
)
[tag__not_in] => Array
(
)
[tag__and] => Array
(
)
[tag_slug__in] => Array
(
)
[tag_slug__and] => Array
(
)
[post_parent__in] => Array
(
)
[post_parent__not_in] => Array
(
)
[author__in] => Array
(
)
[author__not_in] => Array
(
)
)
[tax_query] => WP_Tax_Query Object
(
[queries] => Array
(
)
[relation] => AND
[table_aliases:protected] => Array
(
)
[queried_terms] => Array
(
)
[primary_table] =>
[primary_id_column] =>
)
[meta_query] =>
[date_query] =>
[post_count] => 0
[current_post] => -1
[in_the_loop] =>
[comment_count] => 0
[current_comment] => -1
[found_posts] => 0
[max_num_pages] => 0
[max_num_comment_pages] => 0
[is_single] =>
[is_preview] =>
[is_page] =>
[is_archive] => 1
[is_date] =>
[is_year] =>
[is_month] =>
[is_day] =>
[is_time] =>
[is_author] =>
[is_category] =>
[is_tag] =>
[is_tax] =>
[is_search] =>
[is_feed] =>
[is_comment_feed] =>
[is_trackback] =>
[is_home] =>
[is_404] =>
[is_embed] =>
[is_paged] =>
[is_admin] => 1
[is_attachment] =>
[is_singular] =>
[is_robots] =>
[is_posts_page] =>
[is_post_type_archive] => 1
[query_vars_hash:WP_Query:private] => 1c0b485390fc9607d8008a14177bd63d
[query_vars_changed:WP_Query:private] =>
[thumbnails_cached] =>
[stopwords:WP_Query:private] =>
[compat_fields:WP_Query:private] => Array
(
[0] => query_vars_hash
[1] => query_vars_changed
)
[compat_methods:WP_Query:private] => Array
(
[0] => init_query_flags
[1] => parse_tax_query
)
)
EDIT (Function body presently using):
add_action( 'pre_get_posts', 'filter_albums_further_if_user_id_found');
function filter_albums_further_if_user_id_found($query) {
if(!is_admin())
return;
if( isset($_GET['user_id']) && !empty($_GET['user_id']) ) {
$user_id = $_GET['user_id'];
$query->set('meta_key', 'user_id');
$query->set('meta_value', $user_id);
}
echo '<pre>'; print_r($query); echo '</pre>'; die();
}
This reminded me of a similar problem I had a couple weeks ago. I was wanting to adjust the 'orderby' part of the query, but I believe you can accomplish your task with the same action. Try using the 'pre_get_posts' action instead of that filter. I haven't tested this, so let me know if it works!
CORRECT ANSWER (EDITED after user input):
function user_id_filter( $query ) {
if ( ! is_admin() && !$query->is_main_query() )
return;
if( isset($_GET['user_id']) && !empty($_GET['user_id'])) {
$user_id = $_GET['user_id'];
$query->set( 'author', $user_id );
}
//Debug if necessary
//echo '<pre>'; print_r($query); echo '</pre>'; die();
}
add_action( 'pre_get_posts', 'user_id_filter', 500000000 );
I used this as a reference. https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts

Woocommerce - get product in category with specific attribute

I need to get all product in a category that match an attribute.
Here my code:
$title = isset($instance['title']) ? $instance['title'] : '';
$car_type = isset($instance['cartype']) ? $instance['cartype'] : 'usato';
$car_brand = isset($instance['carbrand']) ? $instance['carbrand'] : '';
$limit = isset($instance['limit']) ? $instance['limit'] : null;
$order = $instance['order'];
$carousel = $instance['carousel'];
$query_args = [
'post_type' => 'product',
'post_status' => 'publish',
'product_cat' => $car_type
];
// Ordino i risultati
if ($order == 'random') {
$query_args['orderby'] = 'random';
} else {
$query_args['orderby'] = 'name';
$query_args['order'] = $order;
}
// Devo limitare il numero di risultati?
if ($limit) {
$query_args['posts_per_page'] = $limit;
}
if ($car_brand != '') {
$query_args['tax_query'] = array(
array(
'key' => 'pa_marca',
'value' => 'nike',
'field' => 'slug',
'compare' => '='
)
);
}
The problem is that I always get 0 result even if there is a product with that category and that attribute.
How should I modify the query?
It looks you use tax_query instead of meta_query. tax_query is for taxonomie filter.
Try this:
$query_args['meta_query'] => array(
array(
'key' => 'pa_marca',
'value' => 'nike',
'compare' => '=',
),
);
WP_Query#Custom_Field_Parameters
Finally I get the solution, this is how you need to query on an attribute:
$query_args['tax_query'] = array(
array(
'key' => 'pa_brand',
'field' => 'slug',
'terms' => 'nike'
)
);
Note that in the key you need to add pa_ to your attribute name and you need to use terms to specify the value of your attribute.

Calculate different order status count and total cash for each order status in Woocommerce

I need to get the order total of a different status in between some days in woocommerce query. For it to loop through all orders in between some day I use the following query:
$args = array(
'post_type' => 'shop_order',
'post_status' => 'publish',
'posts_per_page' => -1,
'date_query' => array(
array(
'after' => array(
'year' => 2016,
'month' =>01,
'day' =>01,
),
'before' => array(
'year' => 2016,
'month' => 01,
'day' =>30,
),
'inclusive' => true,
),
),
);
$loop=new WP_Query($args);
By using this code I can loop through all the query and get the details correctly.
Now I need to get the details into following format
wc-shipped : Total order -> 10 total_cash -> 300$
wc- completed :
Totla order -> 34 total_cash -> 4580$
wc-cancelled : Total order ->
12 total_cash -> 100$
How can I get this detail in this format ?
I know how to get wc-shipped : Total order -> 10
For this I use:
$order_status_get[]=$order->post_status;
$order_status_get= array_count_values($order_status_get);
foreach ($order_status_get as $key => $value) {
echo $key.'->'.$value;
}
But I need the price also. For to get price I can use $order_total_array[]=$order->get_total();
But i don't know how to combine them and get the result in the desired format.
The easiest way I know...
using the WC_Admin_Report class... you can get the result array and manipulate it as you want... sample result is printed below...
include_once( WP_PLUGIN_DIR . '/woocommerce/includes/admin/reports/class-wc-admin-report.php');
$reports = new WC_Admin_Report();
$args = array(
'data' => array(
'_order_total' => array(
'type' => 'meta',
'function' => 'SUM',
'name' => 'total_cash'
),
'ID' => array(
'type' => 'post_data',
'function' => 'COUNT',
'name' => 'total_orders'
),
'post_status' => array(
'type' => 'post_data',
'function' => '',
'name' => 'status'
),
),
'where' => array(
array(
'key' => 'post_date',
'value' => date( 'Y-m-d', strtotime( '02/01/2016' ) ), // starting date
'operator' => '>'
),
array(
'key' => 'post_date',
'value' => date( 'Y-m-d', strtotime( '02/31/2016' ) ), // end date...
'operator' => '<'
),
),
'where_meta' => array(
array(
'meta_key' => 'who',
'meta_value' => 'manik',
'operator' => '='
)
),
'order_status' => array( 'cancelled', 'completed', 'shipped' ),
'group_by' => 'posts.post_status',
'query_type' => 'get_results',
);
$data = $reports->get_order_report_data($args);
print_r($data);
print something like
Array
(
[0] => stdClass Object
(
[total_cash] => 35
[total_orders] => 2
[status] => wc-cancelled
)
[1] => stdClass Object
(
[total_cash] => 315
[total_orders] => 21
[status] => wc-completed
)
[2] => stdClass Object
(
[total_cash] => 211
[total_orders] => 11
[status] => wc-shipped
)
)
then manipulate $data
//print_r($data);
//
$currency = (function_exists('get_woocommerce_currency_symbol'))?get_woocommerce_currency_symbol():'';
foreach($data as $item) {
echo sprintf('<p>%s : Total Orders %s -> Total Cash -> %s%s </p>', $item->status, $item->total_orders, $item->total_cash, $currency);
}
demo of $data. Click Execute code button.
Prints like:
wc-cancelled : Total Orders 2 -> Total Cash -> 35$
wc-completed : Total Orders 21 -> Total Cash -> 315$
wc-shipped : Total Orders 11 -> Total Cash -> 211$
I will give a solution that based on your question .
$order = new WC_Order('your order id ');
In your case
while($loop->have_posts()): $loop->the_post();
$order_id=get_the_ID();
$order = new WC_Order($order_id);
(1) get order status from order we can use $order->post_status
(2) to get order total we can use $order->get_total()
You can combine them and store it in to one array
$order_status_array[]=$order->post_status .'*'.$order->get_total();
here i combined using * , you can use your own.
so that the out put array like
Array ( [0] => wc-cancelled*64 [1] => wc-cancelled*254 [2] =>wc-cancelled*93 [3] => wc-cancelled*44 [4] => wc-cancelled*213 [5] => wc-cancelled*44)
Then use the following code to arrange this array in proper format
$new_array = [];
foreach($order_status_array as $key => $value) {
list($name, $val) = explode('*', $value);
if(array_key_exists($name, $new_array)) {
$new_array[$name]['total_cash'] += $val;
$new_array[$name]['total_order']++;
} else {
$new_array[$name]['total_cash'] = $val;
$new_array[$name]['total_order'] = 1;
}
}
now your array is ready , and it's like
Array(
[wc-cancelled] => Array(
[total_cash] => ...
[total_order] =>...
)
...
)
now use the following code
foreach ($new_array as $l=>$m){
echo $l.'Total Order:->'.$m['total_order'] .'Total Cash:->'.$m['total_cash'].'</br>';
}
. This will work . You can use other good solutions also . Try this .
so entire code is
while($loop->have_posts()): $loop->the_post();
$order_id=get_the_ID();
$order = new WC_Order($order_id);
$order_status_array[]=$order->post_status .'*'.$order->get_total();
endwhile;
$new_array = [];
foreach($order_status_array as $key => $value) {
list($name, $val) = explode('*', $value);
if(array_key_exists($name, $new_array)) {
$new_array[$name]['total_cash'] += $val;
$new_array[$name]['total_order']++;
} else {
$new_array[$name]['total_cash'] = $val;
$new_array[$name]['total_order'] = 1;
}
}
foreach ($new_array as $l=>$m){
echo $l.'Total Order:->'.$m['total_order'] .'Total Cash:->'.$m['total_cash'].'</br>';
}
If I understand your question correctly, you want all orders dumbed down to a list of rows summed by the post_status field, right?
In the end you want something like this:
$order_status = array(
'wc-shipped' => 10,
'wc-completed' => 20,
'wc-cancelled' => 30
);
I see two options:
1) Change the query to utilize posts_groupby to only return summarized columns.
2) Iterate over all the rows in the result set and summarize them by post_status manually. Use an array with the key of the status and increment the value by $order->get_total()

As I read (foreach php) this array stdClass

I have the following code which gives me a query generated , what I need it is to walk the array ( php foreach ) to query the data.
I tried to do with the classic foreach (php) but I foreach throws an error.
Thanks in advance...
Array (
[0] => stdClass Object
(
[_new] =>
[_attributes] => Array
(
[id] => 36
[nombre] => Diana
[estado] => 1
)
[_related] => Array
(
)
[_c] =>
[_pk] => 36
[_alias] => t
[_errors] => Array
(
)
[_validators] =>
[_scenario] => update
[_e] =>
[_m] =>
)
[1] => stdClass Object
(
[_new] =>
[_attributes] => Array
(
[id] => 1
[geoCode] => MAX
)
[_related] => Array
(
)
[_c] =>
[_pk] => 1
[_alias] => t
[_errors] => Array
(
)
[_validators] =>
[_scenario] => update
[_e] =>
[_m] =>
))
As I walk or convert to be read as ?
<?php foreach ($response as $value) {echo $value->nombre;} ?>

Resources