एक एकल क्वेरी
इस बारे में थोड़ा और सोचा और एक मौका है कि आप एक एकल / मुख्य क्वेरी के साथ जा सकते हैं। या दूसरे शब्दों में: जब आप डिफ़ॉल्ट के साथ काम कर सकते हैं तो दो अतिरिक्त प्रश्नों की आवश्यकता नहीं है। और यदि आप एक डिफ़ॉल्ट के साथ काम नहीं कर सकते हैं, तो आपको क्वेरी को विभाजित करने के लिए कितने लूप के लिए एक एकल क्वेरी से अधिक की आवश्यकता नहीं होगी।
आवश्यक शर्तें
पहले आपको एक 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 (स्टैंडर्ड PHP लाइब्रेरी) और इसके इंटरफेस और इटरेटर का उपयोग करता है। अब FilterIterator
हमें जो मिला है वह हमें अपने लूप से आइटम को आसानी से हटाने की अनुमति देता है। यह PHP SPL फ़िल्टर Iterator का विस्तार करता है इसलिए हमें सब कुछ सेट करने की आवश्यकता नहीं है। कोड अच्छी तरह से टिप्पणी की है, लेकिन यहाँ कुछ नोट कर रहे हैं:
accept()
या नहीं - विधि मापदंड है कि आइटम पाशन की अनुमति परिभाषित करने के लिए अनुमति देता है।
- उस पद्धति के अंदर जिसका हम उपयोग करते हैं
WP_Query::the_post()
, इसलिए आप अपनी टेम्पलेट फ़ाइलों के लूप में हर टेम्पलेट टैग का उपयोग कर सकते हैं।
- और साथ ही हम लूप की निगरानी कर रहे हैं और जब हम अंतिम आइटम पर पहुंचते हैं तो पोस्ट को रिवाइंड करते हैं। यह हमारी क्वेरी को रीसेट किए बिना लूप की अनंत मात्रा को लूप करने की अनुमति देता है।
- वहाँ एक कस्टम विधि है कि
FilterIterator
ऐनक का हिस्सा नहीं है deny()
:। यह विधि विशेष रूप से सुविधाजनक है क्योंकि इसमें केवल हमारी "प्रक्रिया या" -स्टेटमेंट नहीं है और हम वर्डप्रेस टेम्पलेट टैग से अलग कुछ भी जानने की आवश्यकता के बिना बाद की कक्षाओं में इसे आसानी से अधिलेखित कर सकते हैं।
कैसे करें लूप?
इस नए Iterator के साथ, हमें 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 के रूप में उपलब्ध है। बस इसे अपलोड और सक्रिय करें। यह loop_start
कार्रवाई पर कॉलबैक के रूप में हर लूप किए गए पोस्ट की आईडी को आउटपुट / डंप करता है। इसका मतलब है कि आपके सेटअप, पोस्ट की संख्या और कॉन्फ़िगरेशन के आधार पर काफी थोड़ा आउटपुट मिल सकता है। कृपया कुछ एबॉर्ट स्टेटमेंट जोड़ें और var_dump()
जो आप देखना चाहते हैं और जहां आप इसे देखना चाहते हैं, उसे अंत में बदल दें। यह सिर्फ अवधारणा का प्रमाण है।