2017 © Pedro Peláez
 

wordpress-plugin combined-query

Modify the WP_Query to support the combined_query parameter. Combine multiple WP_Query queries into a single query.

image

birgir/combined-query

Modify the WP_Query to support the combined_query parameter. Combine multiple WP_Query queries into a single query.

  • Wednesday, June 27, 2018
  • by birgire
  • Repository
  • 7 Watchers
  • 39 Stars
  • 60 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 5 Forks
  • 8 Open issues
  • 7 Versions
  • 2 % Grown

The README.md

Combine Query

WordPress plugin - Combine Query, (*1)

Build Status GitHub license Packagist, (*2)

Description

This experimental plugin allows you to combine multiple WP_Query queries into a single one, using the combined_query attribute., (*3)

This started as an answer on Stackoverflow, see here and here., (*4)

The idea behind this plugin is to combine the SQL queries for each WP_Query() query with UNION or UNION ALL., (*5)

I first noticed this technique in a great answer on WordPress Development by Mike Schinkel., (*6)

I use the trick mentioned here to preserve the order of UNION sub queries., (*7)

This implementation supports combining N sub-queries., (*8)

Notice about the new 1.0.0 version

This version is a total rewrite of the plugin., (*9)

The WP_Combine_Query class has been removed in favour of simply using the combined_query attribute of the WP_Query class., (*10)

Now the plugin only supports PHP versions 5.4+., (*11)

Settings

The supported settings for the combined_query attribute:, (*12)

'combined_query' => [        
    'args'           => [ $args1, $args2, ... ], // Array (default [])
    'union'          => 'UNION',                 // String Possible values are UNION or UNION ALL (default UNION)
    'posts_per_page' => 10,                      // Integer 1,2,...
    'offset'         => 0,                       // Integer 0,1,...
    'orderby'        => 'meta_value_num',        // String (post_name, ..., name, ..., none, meta_value, meta_value_num )
    'order'          => 'DESC',                  // String (ASC,DESC)
]

If you want to remove duplicated posts use UNION, else use UNION ALL., (*13)

Custom filters

There are two custom filters currently available:, (*14)

// Modify combined ordering:
add_filter( 'cq_orderby', function( $orderby ) {
    return $orderby;
});

// Modify sub fields:
add_filter( 'cq_sub_fields', function( $fields ) {
    return $fields;
});

To keep the order by arguments arg1, arg2, ... use:, (*15)

'combined_query' => [
    ...
    'orderby' => 'none',
    ...
]

or, (*16)

add_filter( 'cq_orderby', '__return_empty_string' );
$query = new WP_Query( $args );
remove_filter( 'cq_orderby', '__return_empty_string' );

Installation

Upload the plugin to the plugin folder and activate it., (*17)

To install dependencies with Composer (not required):, (*18)

composer install

or, (*19)

php composer.phar install

within our folder. See here for more information on how to install Composer., (*20)

Then play with the examples below, in your theme or in a plugin., (*21)

Have fun ;-), (*22)

Example 1:

Here we want to display the first published page in an alphabetical order and then the three oldest published posts:, (*23)

//-----------------
// Sub query #1:
//-----------------
$args1 = [
    'post_type'      => 'page',
    'posts_per_page' => 1,
    'orderby'        => 'title',
    'order'          => 'asc',
];

//-----------------
// Sub query #2:
//-----------------
$args2 = [
    'post_type'      => 'post',
    'posts_per_page' => 3,
    'orderby'        => 'date',
    'order'          => 'asc',
];

//---------------------------
// Combined queries #1 + #2:
//---------------------------
$args = [
    'combined_query' => [        
        'args'           => [ $args1, $args2 ],
        'union'          => 'UNION',
        'posts_per_page' => 4,
        'orderby'        => 'none',
    ]
];

//---------
// Output:
//---------
$q = new WP_Query( $args );
if( $q->have_posts() ):
    ?><ul><?php
    while( $q->have_posts() ): $q->the_post();
        ?><li><a href="<?php the_permalink();?>"><?php the_title();?></a></li><?php
    endwhile;
    ?></ul><?php
    wp_reset_postdata();
else:
    _e( 'Sorry no posts found!' );
endif;       

Example 2:

Here we want to display all foo posts with a date query, sorted by comment count and after that all bar posts sorted by comment count. Then we sort all by decreasing comment count., (*24)

//-----------------
// Sub query #1:
//-----------------
$args1 = [ 
    'post_type'           => 'foo',
    'orderby'             => 'comment_count',
    'order'               => 'desc',
    'posts_per_page'      => 100, // adjust to your needs
    'date_query'          => [
        [
            'after' => date('Y-m-d'),
        ],
        'inclusive'  => true,
    ]
];

//-----------------   
// Sub query #2:
//-----------------
$args2 = [
    'post_type'           => 'bar',
    'orderby'             => 'comment_count',
    'order'               => 'desc',
    'posts_per_page'      => 100, // adjust to your needs
];

//--------------------------- 
// Combined queries #1 + #2:
//---------------------------
$args = [
    'combined_query' => [        
        'args'                => [ $args1, $args2 ],
        'posts_per_page'      => 5,
        'paged'               => 2,
        'orderby'             => 'comment_count',
        'order'               => 'desc',
    ]
];

//---------
// Output:
//---------
// See example 1

Example 3:

Let's combine two meta queries and order by a common meta value:, (*25)

//-----------------
// Sub query #1:
//-----------------
$args1 = [
   'post_type'      => 'cars',
   'posts_per_page' => 10,
   'orderby'        => 'title',
   'order'          => 'asc',
   'meta_query'     => [
        [
            'key'      => 'doors',
            'value'    => 0,
            'compare'  => '>=',
            'type'     => 'UNSIGNED'
        ],
    ],
];

//-----------------
// Sub query #2:
//-----------------
$args2 = [
   'post_type'      => 'post',
   'posts_per_page' => 10,
   'orderby'        => 'date',
   'order'          => 'desc',
   'tax_query' => [
        [
            'taxonomy' => 'category',
            'field'    => 'slug',
            'terms'    => 'cars',
        ],
    ],
    'meta_query'     => [
        [
            'key'      => 'doors',
            'value'    => 0,
            'compare'  => '>=',
            'type'     => 'UNSIGNED'
        ],
    ],  
];


//------------------------------
// Order by a common meta value
//------------------------------

// Modify sub fields:
add_filter( 'cq_sub_fields', $callback = function( $fields ) {
    return $fields . ', meta_value';
});

//---------------------------
// Combined queries #1 + #2:
//---------------------------
$args = [
    'combined_query' => [        
    'args'           => [ $args1, $args2 ],
    'posts_per_page' => 5,
    'orderby'        => 'meta_value_num',
    'order'          => 'DESC',
    ]
];

//---------
// Output:
//---------
// See example 1

remove_filter( 'cq_sub_fields', $callback );

Example 4:

We could also combine more than two sub queries, here's an example of four sub-queries:, (*26)

 $args = [ 
    'combined_query' => [        
    'args' => [ $args1, $args2, $args3, $args4 ],
    ...
    ]
  ];

//---------
// Output:
//---------
// See example 1

Example 5:

The above examples are all for secondary queries. So let's add a query to the main home query:, (*27)

add_action( 'pre_get_posts', function( \WP_Query $q ) {   

if( $q->is_home() && $q->is_main_query() ) {

    //-----------------
    // Sub query #1:
    //-----------------
    $args1 = [
       'post_type'      => 'page',
       'posts_per_page' => 1,
       'orderby'        => 'title',
       'order'          => 'asc',
    ];

    //-----------------
    // Original query #2:
    //-----------------    
    $args2 = $q->query;

    //---------------------------
    // Combined queries #1 + #2:
    //---------------------------
    $args = [
        'combined_query' => [
            'args'           => [ $args1, $args2 ],
            'union'          => 'UNION',
            'posts_per_page' => 4,
            'orderby'        => 'none',
        ]
    ];

    //-----------------------
    // Modify the Main query:
    //-----------------------
    $q->set( 'combined_query', $args['combined_query'] );
    }
} );

Changelog

(2022-03-03) - Fixed: Wrong plugin URI in header (Props: therealgilles), (*28)

1.2.2 (2021-02-20) - Fixed: Fixes #14 regarding subsequent queries. (Props: @Suranex), (*29)

1.2.1 (2020-09-14) - Fixed: Readme., (*30)

1.2.0 (2020-09-14) - Added: Support for ordering by 'none'. - Added: Test cases. - Added: Support for adding parameters (posts_per_page, offset, orderby, order) inside combined_query args. - Fixed: Hooks handling for pre_get_posts example. - Adjusted: Examples., (*31)

1.1.1 (2020-09-04) - Added: Example how to keep the order by arguments arg1, arg2, ... - Adjusted: UNION ALL test, (*32)

1.1.0 (2020-09-04) - Added: Ticket #19 - Add test cases for argument order workaround. (Props: therealgilles) - Cleanup: phpcs, (*33)

1.0.5 (2016-05-08) - Fixed: Ticket #8 - Fallback for those who don't use Composer. - Improved: Removed an explicit call to $GLOBALS['wpdb'] through the use keyword. - Improved: Simplified the namespace to only CombinedQuery., (*34)

1.0.4 (2016-04-21) - Fixed: Adjusted the paged bug that sneaked in with verion 1.0.2 yesterday. - Improved: Simplified the example that uses get_query_var() that can now handle default as an input parameter., (*35)

1.0.3 (2016-04-21) - Fixed: Ticket #7 - Not able to set the "UNION ALL" union option - Improved: Inline docs, (*36)

1.0.2 (2016-04-20) - Fixed: Ticket #6 - Escape % in the Generator class. (Props: @DArcMattr) - Improved: Inline docs, (*37)

1.0.1 (2015-11-09) - Fixed: Remove vendor dependency and let the user install it via 'composer install' (Props: @pdufour) - Fixed: Ignore sticky posts in the EmptyQuery class, (*38)

1.0.0 (2015-05-10) - ** Total Plugin Rewrite ** - Closed: Ticket #3 - Added: New classes Main, EmptyQuery and Generator. - Added: Support for 'combined_query' attribute of the WP_Query class. - Added: Support only for PHP 5.4+ - Added: Autoload via Composer. - Added: New filter 'cq_sub_fields' instead of 'cq_sub_fields' - Added: New filter 'cq_orderby' instead of 'cq_orderby', (*39)

0.1.3 (2015-05-09) - Added: Support for ignory_sticky_posts. - Fixed: Minor, (*40)

0.1.2 (2015-05-08) - Added: Support for the GitHub Updater. - Added: New filter 'wcq_sub_fields' - Added: New filter 'wcq_orderby' - Added: New example for meta value ordering - Fixed: Ordering didn't work correctly., (*41)

0.1.1 - Changed: Coding style and autoloading (Props: @egill), (*42)

0.1 Various plugin improvements, for example: - Added: orderby in the combined query. - Added: posts_per_page in the sub queries. - Added: offset in the sub queries. - Added: paged in the sub queries. - Removed: sublimit in the combined query, use posts_per_page instead in sub queries. - Fixed: Issue #1 related to max_num_pages (Props: @hellofantastic)., (*43)

0.0.4 - Added: support for offset in the combined query, (*44)

0.0.3 - Added: GPL2+ License part - Removed: Dropped namespace + anonymous function for wider PHP support., (*45)

0.0.2 - Added: Input parameter 'union' with possible values UNION and UNION ALL. - Fixed: Empty paged resulted in a sql error. (Props: Robert Hue), (*46)

The Versions

27/06 2018

dev-master

9999999-dev

Modify the WP_Query to support the combined_query parameter. Combine multiple WP_Query queries into a single query.

  Sources   Download

MIT

The Requires

 

by Birgir Erlendsson

wordpress

08/05 2016

1.0.5

1.0.5.0

Modify the WP_Query to support the combined_query parameter. Combine multiple WP_Query queries into a single query.

  Sources   Download

MIT

The Requires

 

by Birgir Erlendsson

wordpress

21/04 2016

1.0.4

1.0.4.0

Modify the WP_Query to support the combined_query parameter. Combine multiple WP_Query queries into a single query.

  Sources   Download

GPL2+

The Requires

 

by Birgir Erlendsson

wordpress

21/04 2016

1.0.3

1.0.3.0

Modify the WP_Query to support the combined_query parameter. Combine multiple WP_Query queries into a single query.

  Sources   Download

GPL2+

The Requires

 

by Birgir Erlendsson

wordpress

20/04 2016

1.0.2

1.0.2.0

Modify the WP_Query to support the combined_query parameter. Combine multiple WP_Query queries into a single query.

  Sources   Download

GPL2+

The Requires

 

by Birgir Erlendsson

wordpress

09/11 2015

1.0.1

1.0.1.0

Modify the WP_Query to support the combined_query parameter. Combine multiple WP_Query queries into a single query.

  Sources   Download

GPL2+

The Requires

 

by Birgir Erlendsson

wordpress

10/05 2015

1.0.0

1.0.0.0

Modify the WP_Query to support the combined_query parameter. Combine multiple WP_Query queries into a single query.

  Sources   Download

GPL2+

The Requires

 

by Birgir Erlendsson

wordpress