問題描述
我有 3 個類別,每 15 個帖子,我想做一個查詢資料庫,每個類別只有 5 個第一個帖子,我該怎麼辦?
$q = new WP_Query(array( 'post__in' => array(2,4,8), 'posts_per_page' => **FIRST_5_OF_EACH_CAT** ));
如果不可能,什麼是更有效率,獲取父類別的所有帖子並迴圈遍歷或建立 3 個不同的查詢?
最佳解決方案
你想要的是可能的,但是需要你深入研究我喜歡避免的 SQL(不是因為我不知道,我是一個先進的 SQL 開發人員,而是因為在 WordPress 中,你可以儘可能地使用 API 以儘量減少與未來潛在資料庫結構變化相關的未來相容性問題。)
具有 UNION 運運算元的 SQL 是可能性
要使用 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; 是齊平的。另請注意,我使用全域性變數,允許您透過列出陣列中的類別 lug 子來定義鉤子外的類別。您可以將此程式碼放入外掛或主題的 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("nnUNIONnn",$unioned_selects);
return $join . " INNER JOIN ($unioned_selects) categories ON wp_posts.ID=categories.object_id " ;
}
但是可以是 Side-effects
當然,使用像 posts_join 這樣的查詢修改鉤子總是邀請 side-effects,因為它們在查詢上全域性地執行操作,因此通常需要在 if 中進行修改,if 只在需要時使用它,並且要測試的標準可能很棘手。
專注於最佳化?
然而,我認為你的問題更關心最佳化是關於能夠做一個前 5 名 3 查詢,對嗎?如果是這種情況,那麼也許還有其他使用 WordPress API 的選項?
更好地使用瞬態 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);
總結
雖然是的,但您可以使用 SQL UNION 查詢和 posts_join 篩選器鉤子來進行所需的操作,而不是使用 Transient API 進行快取。
希望這可以幫助?
參考文獻
注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。