Skip to content

Instantly share code, notes, and snippets.

@franz-josef-kaiser
Last active January 18, 2021 19:15
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save franz-josef-kaiser/8464919 to your computer and use it in GitHub Desktop.
Save franz-josef-kaiser/8464919 to your computer and use it in GitHub Desktop.
An example plugin to show the use of the PHP SPL and subsidiary loops with a FilterIterator.
<?php
// Reduced to the minimum
class ThumbnailFilter extends FilterIterator
{
private $wp_query;
public function __construct( Iterator $iterator, WP_Query $wp_query )
{
NULL === $this->wp_query AND $this->wp_query = $wp_query;
parent::__construct( $iterator );
}
public function accept()
{
$this->wp_query->the_post();
$this->wp_query->current_post === $this->wp_query->query_vars['posts_per_page'] // -1
AND $this->wp_query->rewind_posts();
return $this->wp_query->have_posts() AND $this->deny();
}
public function deny()
{
return ! has_post_thumbnail( $this->current()->ID );
}
}
<?php
/**
* Plugin Name: (#130009) Merge Two Queries
* Description: "Merges" two queries by using a <code>RecursiveFilterIterator</code> to divide one main query into two queries
* Plugin URl: http://wordpress.stackexchange.com/questions/130009/how-to-merge-two-queries-together
*/
class ThumbnailFilter extends FilterIterator implements Countable
{
private $wp_query;
private $allowed;
private $counter = 0;
public function __construct( Iterator $iterator, WP_Query $wp_query )
{
NULL === $this->wp_query AND $this->wp_query = $wp_query;
// Save some processing time by saving it once
NULL === $this->allowed
AND $this->allowed = $this->wp_query->have_posts();
parent::__construct( $iterator );
}
public function accept()
{
if (
! $this->allowed
OR ! $this->current() instanceof WP_Post
)
return FALSE;
// Switch index, Setup post data, etc.
$this->wp_query->the_post();
// Last WP_Post reached: Setup WP_Query for next loop
$this->wp_query->current_post === $this->wp_query->query_vars['posts_per_page'] // -1
AND $this->wp_query->rewind_posts();
// Doesn't meet criteria? Abort.
if ( $this->deny() )
return FALSE;
$this->counter++;
return TRUE;
}
public function deny()
{
return ! has_post_thumbnail( $this->current()->ID );
}
public function count()
{
return $this->counter;
}
}
class NoThumbnailFilter extends ThumbnailFilter
{
public function deny()
{
return has_post_thumbnail( $this->current()->ID );
}
}
add_action( 'loop_start', 'wpse130009Query' );
function wpse130009Query()
{
// Only need to remove this callback for the current test
// Else we'd infinitely nest this callback as WP_Query::the_post()
// calls the 'loop_start' filter.
remove_action( current_filter(), __FUNCTION__ );
global $wp_query;
echo number_format_i18n( $wp_query->found_posts );
$arrayObj = new ArrayObject( $wp_query->get_posts() );
$primaryQuery = new ThumbnailFilter( $arrayObj->getIterator(), $wp_query );
$secondaryQuery = new NoThumbnailFilter( $arrayObj->getIterator(), $wp_query );
foreach ( $primaryQuery as $post )
{
var_dump( get_the_ID() );
}
foreach ( $secondaryQuery as $post )
{
var_dump( get_the_ID() );
}
}
@samjco
Copy link

samjco commented Jan 17, 2021

So then the class "ThumbnailFilter" and "NoThumbnailFilter" can be named "FirstQueryResults (or MainQueryResults)" AND "SecondQueryResults"...
I will also attempt to make a real-life example for others who were stumped like me...

@samjco
Copy link

samjco commented Jan 17, 2021

Another question...
Doesn't this show each query results in one after another instead of mixed in together?
So in order words... The $primaryQuery results all shows first and then $secondaryQuery's results:

	foreach ( $primaryQuery as $post )
	{
		var_dump( get_the_ID() );
	}

	foreach ( $secondaryQuery as $post )
	{
		var_dump( get_the_ID() );
	}

How can we mix together? For Instance. What if I want two different results mixed together forming one result that order-by "date" of each post?

@franz-josef-kaiser
Copy link
Author

I am not sure what you are up to. The WP.SE answer explains whats's happening here. If you got a different question, please ask a follow up question on WP.SE directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment