단일 쿼리
이것에 대해 조금 더 생각하면 단일 / 기본 쿼리로 갈 수 있습니다. 즉, 기본 쿼리로 작업 할 때 두 개의 추가 쿼리가 필요하지 않습니다. 또한 기본 쿼리로 작업 할 수없는 경우 쿼리를 분할하려는 루프 수에 관계없이 단일 쿼리 이상이 필요하지 않습니다.
전제 조건
먼저 pre_get_posts
필터 내에서 필요한 값을 설정해야합니다 (다른 답변과 같이) . 당신은 가능성이 설정합니다 posts_per_page
및 cat
. pre_get_posts
-Filter가 없는 예 :
$catID = 1;
$catQuery = new WP_Query( array(
'posts_per_page' => -1,
'cat' => $catID,
) );
// Add a headline:
printf( '<h1>%s</h1>', number_format_i18n( $catQuery->found_posts )
.__( " Posts filed under ", 'YourTextdomain' )
.get_cat_name( $catID ) );
기지 건설
다음으로 필요한 것은 작은 사용자 정의 플러그인입니다 (또는 functions.php
업데이트 또는 테마 변경 중에 이동하지 않는 경우 파일에 넣으십시오 ).
<?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;
}
}
이 플러그인은 PHP SPL (Standard PHP Library) 과 인터페이스 및 반복자를 사용합니다. 이제 우리가 얻는 것은 FilterIterator
루프에서 항목을 편리하게 제거 할 수있게하는 것입니다. PHP SPL Filter Iterator를 확장하므로 모든 것을 설정할 필요는 없습니다. 코드는 잘 주석 처리되어 있지만 다음과 같은 참고 사항이 있습니다.
- 이
accept()
방법을 사용하면 항목 반복 여부를 기준으로 정의 할 수 있습니다.
- 이 방법에서는을 사용
WP_Query::the_post()
하므로 템플릿 파일 루프의 모든 템플릿 태그를 간단하게 사용할 수 있습니다.
- 또한 마지막 항목에 도달하면 루프를 모니터링하고 포스트를 되감습니다. 이렇게하면 쿼리를 재설정하지 않고도 무한한 수의 루프를 반복 할 수 있습니다.
FilterIterator
사양의 일부가 아닌 하나의 사용자 정의 방법이 deny()
있습니다. 이 방법은 "프로세스 여부"문만 포함하므로 특히 편리하며 WordPress 템플릿 태그 외에는 아무 것도 알 필요없이 이후 클래스에서 쉽게 덮어 쓸 수 있습니다.
반복하는 방법?
이 새로운 반복자, 우리는 필요하지 않습니다 if ( $customQuery->have_posts() )
와 while ( $customQuery->have_posts() )
더 이상. foreach
필요한 모든 점검이 이미 완료되었으므로 간단한 진술로 진행할 수 있습니다 . 예:
global $wp_query;
// First we need an ArrayObject made out of the actual posts
$arrayObj = new ArrayObject( $wp_query->get_posts() );
// Then we need to throw it into our new custom Filter Iterator
// We pass the $wp_query object in as second argument to keep track with it
$primaryQuery = new ThumbnailFilter( $arrayObj->getIterator(), $wp_query );
마지막으로 기본 foreach
루프 만 있으면 됩니다. the_post()
모든 템플릿 태그를 삭제 하고 계속 사용할 수도 있습니다 . 전역 $post
객체는 항상 동기화 상태를 유지합니다.
foreach ( $primaryQuery as $post )
{
var_dump( get_the_ID() );
}
자회사 루프
이제 좋은 점은 이후의 모든 쿼리 필터를 처리하기가 매우 쉽다는 것입니다. deny()
메서드를 정의하기 만하면 다음 루프로 넘어갈 수 있습니다. $this->current()
항상 현재 반복되는 게시물을 가리 킵니다.
class NoThumbnailFilter extends ThumbnailFilter
{
public function deny()
{
return has_post_thumbnail( $this->current()->ID );
}
}
deny()
썸네일이있는 모든 게시물을 반복 하도록 정의한 후 썸네일없이 모든 게시물을 즉시 반복 할 수 있습니다.
foreach ( $secondaryQuery as $post )
{
var_dump( get_the_title( get_the_ID() ) );
}
그것을 테스트하십시오.
다음 테스트 플러그인 은 GitHub에서 Gist로 사용할 수 있습니다. 간단히 업로드하고 활성화하십시오. 모든 루프 된 게시물의 ID를 loop_start
조치 에 대한 콜백으로 출력 / 덤프합니다 . 이는 설정, 게시물 수 및 구성에 따라 약간의 출력을 얻을 수 있음을 의미합니다. 중단 문구를 추가 var_dump()
하고 마지막에 s를보고 싶은 곳과보고 싶은 곳으로 변경하십시오. 그것은 단지 개념의 증거 일뿐입니다.