Tek bir sorgu
Bunu biraz daha düşündüm ve tek bir / ana sorgu ile gidebilirsiniz. Başka bir deyişle: Varsayılan soruyla çalışabileceğinizde iki ek sorguya gerek yoktur. Varsayılan bir sorguyla çalışamamanız durumunda, sorguyu kaç tane bölmek istediğinize bakılmaksızın tek bir sorgudan daha fazlasına ihtiyacınız olmayacaktır.
Ön şartlar
Öncelikle, bir pre_get_posts
filtrenin içindeki gerekli değerleri ayarlamanız gerekir (diğer cevabımda gösterildiği gibi) . Orada muhtemelen ayarlayacak posts_per_page
ve cat
. pre_get_posts
-Filter içermeyen örnek :
$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 ) );
Bir üs inşa etmek
İhtiyacımız olan bir sonraki şey küçük bir özel eklentidir (veya functions.php
güncellemeler veya tema değişiklikleri sırasında hareket ettirmeyi düşünmüyorsanız sadece dosyanıza koyun ):
<?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;
}
}
Bu eklenti bir şey yapar: PHP SPL (Standart PHP Kütüphanesi) ve onun arayüzleri ve yineleyicileri kullanır. Şimdi sahip olduğumuz FilterIterator
şey, öğeleri döngüden rahatça çıkarmamıza izin veren bir şey. PHP SPL Filter Iterator'ı genişletir, böylece her şeyi ayarlamamız gerekmez. Kod iyi yorumlanmış, ancak bazı notlar:
accept()
Ya da - yöntem madde döngü izin kriterleri için imkan sağlar.
- Kullandığımız yöntemin
WP_Query::the_post()
içinde, şablon dosyaları döngünüzdeki her şablon etiketini kolayca kullanabilirsiniz.
- Ayrıca, son öğeye ulaştığımızda döngüyü izliyoruz ve mesajları geri alıyoruz. Bu, sorgumuzu sıfırlamadan sonsuz miktarda döngüye girmeyi sağlar.
- Parçası olmayan bir özel yöntem var
FilterIterator
özellikleri: deny()
. Bu yöntem özellikle sadece "sürecimiz ya da değil" durumumuzu içerdiği için uygundur ve WordPress şablon etiketlerinden başka bir şey bilmenize gerek kalmadan sonraki sınıflarda kolayca yazabiliriz.
Döngü nasıl yapılır?
Bu yeni Yineleyici if ( $customQuery->have_posts() )
ile while ( $customQuery->have_posts() )
artık ihtiyacımız yok. Bizim için foreach
gerekli tüm kontroller zaten yapıldığından basit bir açıklama yapabiliriz . Misal:
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 );
Son olarak, varsayılan bir foreach
döngüden başka bir şeye ihtiyacımız yok . Hatta the_post()
tüm şablon etiketlerini bırakıp kullanabiliriz. Global $post
nesne her zaman senkronize kalır.
foreach ( $primaryQuery as $post )
{
var_dump( get_the_ID() );
}
Yardımcı döngüler
Şimdi güzel olan şey, daha sonraki her sorgu filtresinin işlenmesinin oldukça kolay olmasıdır: Sadece deny()
yöntemi tanımlayın ve bir sonraki döngünüz için hazırsınız. $this->current()
her zaman şu anda yayınlanan yazıya işaret eder.
class NoThumbnailFilter extends ThumbnailFilter
{
public function deny()
{
return has_post_thumbnail( $this->current()->ID );
}
}
Artık deny()
küçük resmi olan her gönderiyi döngüye aldığımızı tanımladığımız gibi , tüm yayınları küçük resim olmadan anında döngüleyebiliriz:
foreach ( $secondaryQuery as $post )
{
var_dump( get_the_title( get_the_ID() ) );
}
Dene.
Aşağıdaki test eklentisi GitHub'da Gist olarak kullanılabilir. Sadece yükleyin ve etkinleştirin. Her döngüdeki gönderinin kimliğini loop_start
eylemde geri arama olarak çıktılar / döker . Bu, kurulumunuza, yayın sayısına ve yapılandırmanıza bağlı olarak biraz çıkış alabileceği anlamına gelir. Lütfen bazı iptal ifadeleri ekleyin var_dump()
ve sonunda görmek istediğiniz yere ve nerede görmek istediğinize göre değiştirin. Bu sadece bir kavram kanıtı.