Wordpress ordered by two custom fields meta_key's - php

I have a Woocomerce query working with one meta_key ( 'countdown_date' or 'hour' ).
It sorts the products by a custom 'meta_key' => 'countdown_date' or 'hour' and orders them using 'orderby' => 'meta_value_num'.
I need to join two meta_key's together. ('hour' key only returns the first two ints of a 24hr time).
Result required, products ordered by two custom fields countdown_date and hour
$args = array(
'posts_per_page' => 20,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'live-events'
)),
'post_type' => 'product',
'meta_key' => 'countdown_date',
// need to add second meta key here 'meta_key' => 'hour',
'orderby' => 'meta_value_num',
'order' => 'ASC'
);
$the_query = new WP_Query( $args );
I've looked at loads of similar questions with no results.
Two loops seems overkill and adding the meta_query is not working for me.
Any help would be great. :)
Full working code in the answer below from #Rene_Korss
Could i get a hand add this to functions.php so that the archive will sort the same way as the custom loop.
Below is a simplified version of the function i've got working. I need to add the two meta_key's here too.
add_filter('woocommerce_get_catalog_ordering_args','wdm_change_ordering',10,1);
function wdm_change_ordering($args) {
if(is_product_category()) {
$args['meta_key'] = 'countdown_date';
// need to add second meta key here $args['meta_key'] = 'hour',
$args['orderby'] = 'meta_value';
$args['order'] = 'ASC';
}
return $args;
}

Add both meta keys to meta_query and set orderby to meta_value. Then you can replace it with posts_orderby hook.
<?php
// Override orderby if orderby value = 'meta_value'
function orderby_countdown_date_and_hour( $orderby ){
return str_replace( 'meta_value', 'meta_value, mt1.meta_value', $orderby );
}
$args = array(
'post_type' => 'product',
'posts_per_page' => 20,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'live-events'
)
),
'meta_query' => array(
array(
'key' => 'countdown_date',
'value' => '',
'compare' => '!='
),
array(
'key' => 'hour',
'value' => '',
'compare' => '!='
)
),
'orderby' => 'meta_value',
'order' => 'ASC'
);
// Replace orderby
add_filter( 'posts_orderby', 'orderby_countdown_date_and_hour' );
// Query
$the_query = new WP_Query( $args );
// Remove our orderby
remove_filter( 'posts_orderby', 'orderby_countdown_date_and_hour' );
This results in
ORDER BY dbprefix_postmeta.meta_value, mt1.meta_value ASC
which means
ORDER BY countdown_date, hour ASC

Related

WooCommerce: Show only terms with products in stock

I'm using get_terms to show a list of terms. It works fine so far.
But I want to hide every term with out of stock products.
If I use 'hide_empty' => true it wouldn't work because the products are there and published.
Is there a way to add the _stock meta field to the get_terms function?
Unfortunately I have to use get_terms.
Here's my code (it's a lot bigger but that's the part):
$terms = get_terms( array(
'taxonomy' => 'product_tax',
'orderby' => 'name',
'hide_empty' => true,
) );
5 months ago but maybe it will help someone : I'm facing the same issue and all I found is to make a foreach to unset the empties values.
foreach ($terms as $key => $term) {
$args = array(
'post_type' => 'product',
'paged' => 1,
'posts_per_page' => 1,
'order' => 'DESC',
'post_status' => 'publish',
'orderby' => 'publish_date',
'meta_query' => array( array(
'key' => '_stock_status',
'value' => 'instock',
) ),
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $term->term_id
)
)
);
$loop = new WP_Query( $args );
if($loop->post_count < 1) {
unset($terms[$key]);
}
}

How to query posts by ACF field but then also order by a separate ACF field?

I am using WP_Query to get posts that have a specific value in one of the ACF fields. I also need to order them by a separate ACF field. I am not sure how to accomplish this. Everything I've read says to use 'orderby' => 'meta_value' but I believe thats the value of the field I'm filtering the posts by, which is not what I want.
This is what I have right now..
$args = array(
'post_type' => 'contacts',
'posts_per_page' => -1,
'meta_key' => 'department',
'meta_value' => 'Transportation',
'orderby' => 'meta_value'
);
$the_query = new WP_Query( $args );
I need to orderby an ACF field named last_name.
It's possible to assign a name to a meta query, and then refer to that name in your orderby. Something like this.
$args = array (
'post_type' => 'contacts',
'post_status' => 'publish',
'nopaging' => true,
'posts_per_page' => -1,
'meta_query' => array( 'main_query' => array(
'key' => 'department',
'value' => 'Transportation'
), 'orderby_query' => array(
'key' => 'last_name',
)
),
'orderby' => array(
'orderby_query' => 'ASC',
),
);
$the_query = new WP_Query( $args );

Order by custom Woocommerce product sorting in a WP_Query

I have created a shortcode to display products by category with the query below:
$atts = shortcode_atts( array (
'type' => 'product',
'posts' => -1,
'category' => '',
), $atts, 'list_products' );
$query = new WP_Query( array(
'post_type' => $atts['type'],
'posts_per_page' => $atts['posts'],
'tax_query' => array( array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $atts['category'],
) ),
) );
This is all fine, however I am trying to use the order by attribute when I sort the products using the custom sort shown here
I have added: 'orderby' => 'modified', and tried some others from here.
Two questions:
Which attribute do I need to use to sort when using custom sorting
And
What do I need to do to make my orderby attribute work when added to the above query? Because it which ever attribute value I use it always sorts by published descending.
When you use custom sorting for Woocommerce products, it set some values for each product in wp_posts database table under menu_order column.
Then you just need to add 'orderby' => 'menu_order', in your WP_Query, so in your code:
$atts = shortcode_atts( array (
'type' => 'product',
'posts' => -1,
'category' => '',
), $atts, 'list_products' );
$query = new WP_Query( array(
'post_type' => $atts['type'],
'posts_per_page' => $atts['posts'],
'tax_query' => array( array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $atts['category'],
) ),
'orderby' => 'menu_order',
// 'order' => 'DESC',
) );
It will work (by default the order sorting argument is set to ASC normally).

Order wp_query by numeric custom field

I'm trying to allow users to sort a list of results from a wp_query by a numeric custom field value. Users can click a button to change the sort by values, but when Price is selected, this is what the wp_query looks like:
'meta_key' => 'adult',
'orderby' => 'meta_value_num',
'order' => 'ASC',
The field is the numeric field from ACF (ACF 5 beta is being used) with a step size of 0.01 to allow for prices like 9.99.
However, if I run this query it returns no results every time, even when there are definitely results that should be matching.
Any ideas where I'm going wrong?
EDIT - full query
$keywordString = $_SESSION['search']['keyword'];
$keywords = explode(', ', $keywordString);
$taxQuery = array(
'relation' => 'AND',
array (
'taxonomy' => 'main-cat',
'field' => 'slug',
'terms' => $_SESSION['search']['cat']
)
);
if( $_SESSION['search']['keyword'] != '' ) {
$taxQuery[] = array(
'taxonomy' => 'sub-cat',
'field' => 'name',
'terms' => $keywords
);
}
$args = array(
// general
'post__in' => $postIDs,
'post_type' => 'event',
'posts_per_page' => 10,
'paged' => $paged,
'cache_results' => false,
'meta_key' => $_SESSION['search']['sort-key'], // becomes 'adult'
'orderby' => $_SESSION['search']['sort-by'], // becomes 'meta_value_num'
'order' => 'ASC',
// category filter
'tax_query' => $taxQuery,
// date filter
meta_query' => array(
'relation' => 'AND',
array(
'key' => 'date_%_start-date',
'value' => $when,
'compare' => '>=',
'type' => 'NUMERIC'
),
array (
'key' => 'date_%_end-date',
'value' => $when2,
'compare' => '<=',
'type' => 'NUMERIC'
)
)
);
$temp = $wp_query;
$wp_query = null;
$wp_query = new WP_Query( $args );

WordPress Query: ORDER BY CASE WHEN

I want to first display the posts that match a particular meta_key => cr_id and order those by another 'meta_key' => 'cr_list_price' and then display the rests of the posts that are also ordered by 'meta_key' => 'cr_list_price'.
This is my current code which does everything I want except show the posts where cr_id = 4.
$args = array(
'post_type' => 'properties',
'paged' => get_query_var( 'paged' ),
'meta_query' => array(
array(
'key' => 'cr_list_price',
'value' => array($minPrice, $maxPrice),
'type' => 'numeric',
'compare' => 'BETWEEN'
),
array(
'key' => 'cr_prop_bed',
'value' => $beds,
'compare' => '>='
),
),
'orderby' => 'meta_value_num',
'meta_key' => 'cr_list_price'
);
$loop = new WP_Query( $args );
If I was using raw MySQL I'd do something like ORDER BY CASE WHEN in my query, however I'm not sure how or if I can accomplish this with WordPress.
I wonder if you could add a filter to the query by adding that little extension on there. I'm thinking maybe posts_orderby
Function
function filter_case($orderby = '') {
$orderby .= 'CASE WHEN [some conditions]';
return $orderby;
}
Before Query
add_filter( 'posts_orderby', 'filter_case' );
$wp_query = new WP_Query($args);
remove_filter( 'posts_orderby', 'filter_case' );
I cant gaurantee this will work first time but it could be worked on if you think it's worth pursuing? List of WP_Query filters are here.

Categories