birgire / wp-combine-queries Goto Github PK
View Code? Open in Web Editor NEWWordPress: Combine multiple WP_Query() queries into a single one, through the custom 'combined_query' attribute of the WP_Query class.
License: MIT License
WordPress: Combine multiple WP_Query() queries into a single one, through the custom 'combined_query' attribute of the WP_Query class.
License: MIT License
I've been combining 3 sub queries on a site with no problems until recently. Sometimes one or two of the sub queries are empty arrays, but that hasn't posted a problem until recently. In the last week or so we've had issues with the queries returning ACF field group posts. I still have no idea why, as I'm specifying a particular post type in the sub queries. To fix this I needed to not include the empty arrays in the 'combined_query' argument array.
Previously my code looked like this:
$query = new WP_Query( array(
'combined_query' => array(
'args' => array( $sub_query1, $sub_query2, $sub_query3 ),
'orderby' => 'none',
'posts_per_page' => $per_page,
'paged' => $cur_page,
),
) );
And now it looks like this:
$combined_queries = [];
if ( ! empty( $sub_query1 ) ) {
array_push( $combined_queries, $sub_query1 );
}
if ( ! empty( $sub_query2 ) ) {
array_push( $combined_queries, $sub_query2 );
}
if ( ! empty( $sub_query3 ) ) {
array_push( $combined_queries, $sub_query3 );
}
$query = new WP_Query( array(
'combined_query' => array(
'args' => $combined_queries,
'orderby' => 'none',
'posts_per_page' => $per_page,
'paged' => $cur_page,
),
) );
Hopefully this helps anyone facing the same issue.
Hey there using the latest classes on ver 4 of WP and I'm getting a extra empty page,
My two args look like this:
$meta_query = array('relation' => 'AND',
array(
'key' => 'property_status',
'value' => 'Sold',
'compare' => '!='
)
);
$args1 = array(
'post_type' => 'property',
'orderby' => 'date',
'meta_key' => 'property_status',
'order' => 'DESC',
'post_status' => 'publish',
'meta_query' => $meta_query,
);
//$listings = new WP_Query( $args );
$meta_query_sold = array('relation' => 'AND',
array(
'key' => 'property_status',
'value' => 'Sold',
'compare' => '='
)
);
$args2 = array(
'post_type' => 'property',
'orderby' => 'date',
'meta_key' => 'property_status',
'order' => 'DESC',
'post_status' => 'publish',
'meta_query' => $meta_query_sold,
);
$args = array(
'posts_per_page' => $posts_per_page,
'paged' => $paged,
'sublimit' => 1000,
'args' => array( $args1, $args2 ),
);
$wp_query = new WP_Combine_Queries( $args );
I've tried to used this a custom post type and it doesn't seem to work. It still shows the normal posts. Not sure what's wrong.
my code looks like this:
$args1 = [
'post_type' => 'products',
'post_status' => 'publish',
'meta_query' => [
[
'key' => 'product_id',
'compare' => 'EXISTS',
],
],
'orderby' => 'date',
'order' => 'DESC',
];
//-----------------
// Sub query #2:
//-----------------
$args2 = [
'post_type' => 'products',
'post_status' => 'publish',
'meta_query' => [
[
'key' => 'product_id',
'compare' => 'NOT EXISTS',
],
],
'orderby' => 'date',
'order' => 'DESC',
];
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
//---------------------------
// Combined queries #1 + #2:
//---------------------------
$args3 = [
'posts_per_page' => 12,
'pagination' => true,
'combined_query' => [
'args' => [ $args1, $args2 ],
'union' => 'UNION',
],
'paged'=>$paged,
];
//---------
// Output:
//---------
$q = new WP_Query( $args3 );
The following lines broke subsequent queries which are not use combined_query
(after a query with combined_query
was used) because the filter are now always applied. The filter posts_request
and posts_orderby
should only be added by pre_get_posts
,
wp-combine-queries/includes/Main.php
Lines 107 to 108 in 5fc550f
Parse error: syntax error, unexpected '[' in /wp-content/plugins/wp-combine-queries-master/includes/Main.php on line 14
Upon setting this up when I hit page/2 for any loop I get a 404 page.
Does this work when using multipage archives and am I missing something or does this feature not exist?
First โ thanks for this plugin! One of my uses is on an event listing page to first show upcoming events in ASC order and then show past events in DESC order. But I was having a hell of a time getting them to actually sort correctly! The dates within each query were always jumbled.
I took some guidance from this StackOverflow posts: https://stackoverflow.com/questions/30192885/how-to-sort-data-in-mysql-union-subquery
Essentially, it claimed that the outer query would negate any sorting of inner queries. It was useful to assign an ID to the records in each subquery, to preserve that order, and then reiterate the sorting with the outer query. This is messy, but it worked:
// Needed a global variable here to increment.
$cq_sortfield_count = 0;
// Modify sub fields:
add_filter( 'cq_sub_fields', $callback = function( $fields ) {
global $cq_sortfield_count;
$cq_sortfield_count++;
// Create a new field with an ID for each query.
return $fields . ', meta_value, "' . $cq_sortfield_count . '" AS sortfield';
});
// Modify combined ordering:
add_filter( 'cq_orderby', function( $orderby ) {
$current_time = time() - ( 5 * 60 * 60 );
// Here we first sort by the new field which then allows a second layer of sorting within the two groups.
return 'sortfield ASC, IF( combined.meta_value > ' . $current_time . ', combined.meta_value, 0) ASC, IF( combined.meta_value <= ' . $current_time . ', combined.meta_value, null) DESC';
});
Just sharing in case this helps at all!
I'm using pre_get_posts to inserted a combined query but it's removing the original query completely.
SELECT SQL_CALC_FOUND_ROWS *
FROM ( (SELECT wp_posts.*
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 (5) )
AND wp_posts.post_type = 'document_cpt'
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'acf-disabled'
OR wp_posts.post_status = 'private')
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 20 ) ) as combined
ORDER BY post_title DESC
LIMIT 0, 20
Isn't there supposed to be a UNION in there or something?
After apply this plugin to search, the results are not filter based on the search keyword. Kindly help us.
Thanks!
Hi!
This is an awesome plugin. I've used it and it works great. This time, I'm trying something different and was wondering if you could perhaps shed some light.
I'm using Event Organiser for event management.
Using Combine Queries, I'm trying to query posts and events. I know Combine Queries is working because it works just fine when I'm not querying events.
`
// -----------------
// Sub query #1:
// -----------------
$args1 = [
'post_type' => array( 'news' ),
// 'fields' => 'ids',
'posts_per_page' => 100,
];
// -----------------
// Sub query #2:
// -----------------
$args2 = [
'post_type' => 'event',
'suppress_filters' => false,
// 'fields' => 'ids',
'posts_per_page' => 100,
];
// ---------------------------
// Combined queries #1 + #2:
// ---------------------------
$args = [
'combined_query' => [
'args' => [ $args1, $args2 ],
'union' => 'UNION',
'posts_per_page' => 12,
'post_status' => 'publish',
// 'orderby' => 'none',
],
];
// ---------
// Output:
// ---------
$query = new WP_Query( $args );`
This is a very basic query for starting out. Once I get this working, I plan to make the event's query a bit more advanced. That's why I'm using this and not simply post_type => array( 'news', 'event' )
.
When the above runs, there are no posts. When I change 'event' to another post type, it works just fine. It's definitely something related to the event post type but I'm not sure what. Have any ideas off the top of your head?
Thanks for any assistance!
Looks like it's not possible to set the "UNION ALL" option in the union
settings.
Hello!
Thanks for the plugin :)
I'd like to order the posts from $arg1 first then $arg2, but the post is mixed. Am I doing anything wrong? Please see the codes below. (It is to show posts before "end_date" first" and then after "end date", which means expired) Thank you!
$today = date('Ymd');
$args1 = [
'category_name' => $term_slug,
'posts_per_page' => 100000,
'meta_query' => [
[
'key' => 'end_date',
'value' => $today,
'compare' => '>=',
],
],
'orderby' => 'modified',
'order' => 'DESC',
];
$args2 = [
'category_name' => $term_slug,
'posts_per_page' => 100000,
'meta_query' => [
[
'key' => 'end_date',
'value' => $today,
'compare' => '<',
],
],
'orderby' => 'modified',
'order' => 'DESC',
];
$final_query_args = [
'posts_per_page' => 12,
'ignore_sticky_posts' => 1,
'combined_query' => [
'args' => [ $args1,$args2 ],
'union' => 'UNION',
]
];
$final_query_args['paged'] = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
$final_query = new WP_Query( $final_query_args );
Hi, is there a way to indicate which query the posts have come from? For example if I run two queries combined I want to know when the posts from the first query ends and when the posts from the second query begins.
I am trying to create an events calendar which fetches events from a user defined date and orders them according to a priority field. Then it runs another query for the next day and returns those posts also sorted by priority (Eventually it will do this for up to five subsequent days).
So both the queries are the same, except the date changes:
$day1_args = array(
'post_type' => 'events',
'post_status' => 'publish',
'posts_per_archive_page' => 100,
'tax_query' => array(
array(
'taxonomy' => 'event_location',
'field' => 'slug',
'terms' => $county_terms,
'include_children' => true
),
array(
'taxonomy' => 'event_category',
'field' => 'slug',
'terms' => $category_terms,
'include_children' => true
)
),
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'start_date',
'value' => $post_vars['date'],
'compare' => '<=',
'type' => 'DATE',
),
array(
'key' => 'end_date',
'value' => $post_vars['date'],
'compare' => '>=',
'type' => 'DATE',
)
),
'meta_key' => 'priority',
'orderby' => 'priority',
'order' => 'ASC',
);
$day2_args = array(
'post_type' => 'events',
'post_status' => 'publish',
'tax_query' => array(
array(
'taxonomy' => 'event_location',
'field' => 'slug',
'terms' => $county_terms,
'include_children' => true
),
array(
'taxonomy' => 'event_category',
'field' => 'slug',
'terms' => $category_terms,
'include_children' => true
)
),
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'start_date',
'value' => add_day_to_date($post_vars['date']),
'compare' => '<=',
'type' => 'DATE',
),
array(
'key' => 'end_date',
'value' => add_day_to_date($post_vars['date']),
'compare' => '>=',
'type' => 'DATE',
)
),
'meta_key' => 'start_date',
'orderby' => 'start_date',
'order' => 'DESC',
);
// Modify combined ordering:
add_filter( 'cq_orderby', function ( $orderby ) {
return '"meta value" ASC';
} );
// Modify sub fields:
add_filter( 'cq_sub_fields', function ( $fields ) {
return $fields . ', "meta value"';
} );
$args = [
'posts_per_page' => $posts_per_page,
'paged' => $paged,
'combined_query' => [
'orderby' => [ 'priority' => 'asc', 'priority' => 'asc' ],
'args' => [ $day1_args, $day2_args ],
'union' => 'UNION ALL',
]
];
And this works, except I need to know when the posts from the second query come through so I can add a bit of html with the date ahead of the posts. I'm not sure how to do that.
Hello,
I want to display my posts with different sizes on my homepage (with a pagination)
In order to achieve this, I added a custom field "news_or_big" which equals "news" for little news, and "big" for big articles.
The problem is that at the end, the order of my queries is not respected and I get :
I don't know if I did it the right way, here's my code :
//-----------------
// Sub query #1:
//-----------------
$args1 = [
// get field news
'post_type' => 'post',
'category__not_in' => 31,
'posts_per_page' => 2,
'meta_key' => 'news_or_big',
'meta_value' => 'news'
];
//-----------------
// Sub query #2:
//-----------------
$args2 = [
// get big news
'post_type' => 'post',
'category__not_in' => 31,
'posts_per_page' => 1,
'meta_key' => 'news_or_big',
'meta_value' => 'big'
];
//-----------------
// Sub query #3:
//-----------------
$args3 = [
// get field news
'post_type' => 'post',
'category__not_in' => 31,
'posts_per_page' => 2,
'meta_key' => 'news_or_big',
'meta_value' => 'news',
'offset' => 2,
];
//-----------------
// Sub query #4:
//-----------------
$args4 = [
// get big news
'post_type' => 'post',
'category__not_in' => 31,
'posts_per_page' => 1,
'meta_key' => 'news_or_big',
'meta_value' => 'big',
'offset' => 1,
];
//---------------------------
// Combined queries #1 + #2 + #3 + #4:
//---------------------------
$args = [
'posts_per_page' => 6,
'orderby' => 'meta_value',
'paged' => $paged,
'combined_query' => [
'args' => [$args1, $args2, $args3, $args4],
'union' => 'UNION',
]
];
Thank you for your help!
I think it would be more flexible to add a support for a custom argument, like combine_queries
, in WP_Query
for the multiple queries, instead of using the extended WP_Combine_Query
class.
Then we could easily adjust the main query via the pre_get_posts
hook:
add_action( 'pre_get_posts', function( $q )
{
if( ! is_admin() && $q->is_main_query() )
{
// Sub query #1:
// Sub query #2:
// ...etc
// Combine subqueries #1 + #2 + ... etc
$q->set( 'combine_queries', [ $args1, $args2 ] )
}
} );
or secondary queries with:
$args = [
'posts_per_page' => 5,
'orderby' => 'meta_value',
'order' => 'DESC',
'combine_queries' => [ $args1, $args2 ],
];
WP_Query( $args );
I'm trying to add on to the main search but getting the warning PHP Warning: sprintf(): Too few arguments in /var/www/wp-content/plugins/wp-combine-queries-master/includes/Generator.php on line 98
In my 'pre_get_posts'
handler I have:
function document_posts_search_filter( $query ) {
if ( !is_admin() && $query->is_main_query() ) {
if ($query->is_search) {
if ( isset( $_GET['doctype'] ) && $_GET['doctype'] != "" ) {
$sub_query_args = array( 'args' => array( create_document_type_args() ), 'union' => 'UNION' );
$query->set( 'combined_query', $sub_query_args);
}
}
$query->set( 'post_type', array( 'document_cpt' ) );
}
return $query;
}
add_filter( 'pre_get_posts', 'document_posts_search_filter' );
where create_document_typs_args
returns query args:
function create_document_type_args() {
$tax_args = array( 'relation' => 'OR' );
// document types taxonomy
$doctypes = explode(",", get_query_var( 'doctype' ) );
$tax_args[] = array(
'taxonomy' => 'document_type',
'field' => 'slug',
'terms' => $doctypes,
'operator' => 'IN',
);
// create the query arguments
$args = array(
'post_type' => array( 'document_cpt' ),
'tax_query' => $tax_args,
);
return $args;
}
What am I doing wrong here?
Hello,
I have been trying to install your plugin on my wordpress install (4.7) and I cannot activate it (Parse error: syntax error, unexpected T_STRING in /home/gmemzeuq/new/wp-content/plugins/wp-combine-queries-master/combined-query.php on line 13).
Is there any way you could help?
Thanks for your great work.
Kindly help to apply in wordpress default search.
Thanks!
The plugin header has the following URI: https://github.com/birgire/wp-combined-queries
instead of the new one: https://github.com/birgire/wp-combine-queries
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.