สิ่งที่คุณต้องการเป็นไปได้ แต่จะทำให้คุณต้องเจาะลึกลงไปในSQL ที่ฉันต้องการหลีกเลี่ยงเมื่อใดก็ตามที่เป็นไปได้ (ไม่ใช่เพราะฉันไม่รู้ฉันเป็นนักพัฒนา SQL ขั้นสูง แต่เนื่องจากใน WordPress คุณต้องการใช้ API เมื่อทำได้เพื่อลดปัญหาความเข้ากันได้ในอนาคตที่เกี่ยวข้องกับการเปลี่ยนแปลงโครงสร้างฐานข้อมูลที่อาจเกิดขึ้นในอนาคต)
SQL ที่มีตัวUNION
ดำเนินการเป็นไปได้
การใช้ SQL สิ่งที่คุณต้องการเป็นUNION
ผู้ประกอบการในการค้นหาของคุณบางอย่างเช่นสมมตินี้ทากหมวดหมู่ของคุณมี"category-1"
, "category-1"
และ"category-3"
:
SELECT * FROM wp_posts WHERE ID IN (
SELECT tr.object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='category-1'
LIMIT 5
UNION
SELECT tr.object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='category-2'
LIMIT 5
UNION
SELECT tr.object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='category-3'
LIMIT 5
)
คุณสามารถใช้ SQL UNION กับposts_join
ตัวกรองได้
การใช้ด้านบนคุณสามารถโทรออกได้โดยตรงหรือคุณสามารถใช้posts_join
ตะขอตัวกรองดังนี้ หมายเหตุฉันใช้PHP heredocเพื่อให้แน่ใจว่าSQL;
จะล้างซ้าย นอกจากนี้โปรดทราบว่าฉันใช้ var ส่วนกลางเพื่อให้คุณสามารถกำหนดหมวดหมู่ภายนอก hook ได้โดยแสดงทากหมวดหมู่ในอาร์เรย์ คุณสามารถใส่รหัสนี้ในปลั๊กอินหรือในfunctions.php
ไฟล์ธีมของคุณ:
<?php
global $top_5_for_each_category_join;
$top_5_for_each_category_join = array('category-1','category-2','category-3');
add_filter('posts_join','top_5_for_each_category_join',10,2);
function top_5_for_each_category_join($join,$query) {
global $top_5_for_each_category_join;
$unioned_selects = array();
foreach($top_5_for_each_category_join as $category) {
$unioned_selects[] =<<<SQL
SELECT object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='{$category}'
LIMIT 5
SQL;
}
$unioned_selects = implode("\n\nUNION\n\n",$unioned_selects);
return $join . " INNER JOIN ($unioned_selects) categories ON wp_posts.ID=categories.object_id " ;
}
แต่อาจมีผลข้างเคียง
แน่นอนว่าการใช้ hooks การแก้ไขแบบสอบถามอย่างเช่นposts_join
จะเชิญผลข้างเคียงในการที่พวกเขากระทำทั่วโลกเกี่ยวกับการค้นหาและดังนั้นคุณมักจะต้องห่อการปรับเปลี่ยนของคุณในการif
ที่จะใช้มันเมื่อจำเป็นเท่านั้นและเกณฑ์การทดสอบอะไรจะยุ่งยาก
มุ่งเน้นที่การเพิ่มประสิทธิภาพแทนหรือไม่
อย่างไรก็ตามฉันคิดว่าคำถามของคุณเป็นเรื่องเกี่ยวกับการเพิ่มประสิทธิภาพมากกว่าเกี่ยวกับความสามารถในการทำแบบสอบถาม 5 ครั้ง 3 ด้านบนใช่มั้ย หากเป็นเช่นนั้นอาจมีตัวเลือกอื่น ๆ ที่ใช้ WordPress API หรือไม่
ดีกว่าการใช้ Transients API สำหรับการแคชหรือไม่
ฉันคิดว่าโพสต์ของคุณจะไม่เปลี่ยนแปลงอย่างนั้นใช่ไหม? เกิดอะไรขึ้นถ้าคุณยอมรับสาม (3) แบบสอบถามตีเป็นระยะ ๆ แล้วแคชผลโดยใช้Transients API ? คุณจะได้รหัสที่สามารถบำรุงรักษาได้และประสิทธิภาพที่ยอดเยี่ยม ดีกว่าUNION
แบบสอบถามข้างต้นเล็กน้อยเนื่องจาก WordPress จะจัดเก็บรายการโพสต์เป็นอาร์เรย์ลำดับในหนึ่งระเบียนของwp_options
ตาราง
คุณสามารถนำตัวอย่างต่อไปนี้และวางลงในรูทเว็บไซต์ของคุณtest.php
เพื่อทดสอบ:
<?php
$timeout = 4; // 4 hours
$categories = array('category-1','category-2','category-3');
include "wp-load.php";
$category_posts = get_transient('top5_posts_per_category');
if (!is_array($category_posts) || count($category_posts)==0) {
echo "Hello Every {$timeout} hours!";
$category_posts = array();
foreach($categories as $category) {
$posts = get_posts("post_type=post&numberposts=5&taxonomy=category&term={$category}");
foreach($posts as $post) {
$category_posts[$post->ID] = $post;
}
}
set_transient('top5_posts_per_category',$category_posts,60*60*$timeout);
}
header('Content-Type:text/plain');
print_r($category_posts);
สรุป
ในขณะที่ใช่คุณสามารถทำสิ่งที่คุณขอใช้UNION
แบบสอบถามSQL และposts_join
ตัวกรองเบ็ดคุณน่าจะดีกว่าเสนอใช้แคชกับTransients APIแทน
หวังว่าจะช่วยได้ไหม