แบบสอบถามเดียว
คิดเกี่ยวกับเรื่องนี้อีกเล็กน้อยและมีโอกาสที่คุณจะสามารถไปกับคำค้นหาหลักเดียว / หรือกล่าวอีกนัยหนึ่ง: ไม่จำเป็นต้องมีสองข้อความค้นหาเพิ่มเติมเมื่อคุณสามารถทำงานกับคำสั่งเริ่มต้นได้ และในกรณีที่คุณไม่สามารถทำงานกับค่าเริ่มต้นได้คุณจะไม่ต้องการแบบสอบถามมากกว่าหนึ่งแบบสอบถามไม่ว่าคุณต้องการแยกลูปกี่ครั้ง
ข้อกำหนดเบื้องต้น
ก่อนอื่นคุณต้องตั้งค่า (ดังแสดงในคำตอบอื่น ๆ ของฉัน) ค่าที่ต้องการภายในpre_get_posts
ตัวกรอง มีคุณมีแนวโน้มที่จะตั้งค่าและposts_per_page
cat
ตัวอย่างที่ไม่มีตัวpre_get_posts
กรอง:
$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
ที่ช่วยให้เราสามารถลบรายการออกจากวงของเราได้อย่างสะดวก มันขยายตัวกรอง Iterator PHP SPL ดังนั้นเราไม่จำเป็นต้องตั้งค่าทุกอย่าง รหัสมีความเห็นดี แต่นี่เป็นบันทึกย่อบางส่วน:
accept()
วิธีการช่วยให้การกำหนดเกณฑ์ที่ช่วยให้บ่วงรายการ - หรือไม่
- ภายในวิธีการที่เราใช้
WP_Query::the_post()
ดังนั้นคุณสามารถใช้เทมเพลตแท็กทุกอันในลูปไฟล์เทมเพลตของคุณ
- และเช่นกันเรากำลังตรวจสอบลูปและกรอกลับโพสต์เมื่อเราไปถึงไอเท็มสุดท้าย วิธีนี้ทำให้สามารถวนซ้ำลูปได้ไม่ จำกัด โดยไม่ต้องรีเซ็ตเคียวรีของเรา
- มีวิธีการที่กำหนดเองหนึ่งที่ไม่ได้เป็นส่วนหนึ่งของการเป็นรายละเอียด:
FilterIterator
deny()
วิธีนี้สะดวกมากเป็นพิเศษเนื่องจากมันมีเพียง "กระบวนการหรือไม่" ของเรา - สถานะและเราสามารถเขียนทับมันในคลาสที่ใหม่กว่าโดยไม่จำเป็นต้องรู้อะไรนอกเหนือจากแท็กแม่แบบ WordPress
วิธีการวนซ้ำ
ด้วย 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() ) );
}
ทดสอบมัน
ปลั๊กอินทดสอบต่อไปนี้มีให้เป็น Gist ใน GitHub เพียงอัปโหลดและเปิดใช้งาน มันส่งออก / ทิ้ง ID ของทุกโพสต์ลูปเป็นโทรกลับในการloop_start
ดำเนินการ ซึ่งหมายความว่าอาจได้รับผลลัพธ์เล็กน้อยขึ้นอยู่กับการตั้งค่าจำนวนโพสต์และการกำหนดค่าของคุณ โปรดเพิ่มคำสั่งยกเลิกบางส่วนและแก้ไขvar_dump()
s ในตอนท้ายให้เป็นสิ่งที่คุณต้องการดูและที่ที่คุณต้องการดู มันเป็นเพียงการพิสูจน์แนวคิด