题
我有3个类别的每15个帖子,我想对DB进行一个查询,每类仅带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 最大程度地减少与未来潜在数据库结构变化有关的未来兼容性问题。)
SQL带有 UNION
操作员有可能
要使用SQL,您需要的是 UNION
查询中的操作员,假设您的类别slug是 "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联合与 posts_join
筛选
使用以上您可以 只是直接打电话 或者您可以 用一个 posts_join
过滤器钩 如下所示;注意我正在使用 PHP Heredoc 因此,请确保 SQL;
剩下冲洗。另请注意,我使用了全局var来允许您通过在数组中列出类别sl来定义钩子之外的类别。您可以将此代码放在插件或主题中 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 " ;
}
但是可以有副作用
当然使用查询修改挂钩 posts_join
始终邀请副作用,因为它们在全球范围内作用于查询,因此您通常需要将修改包裹在一个 if
只有在需要时使用它,以及要测试的标准可能很棘手。
专注于优化?
但是,我认为您的问题是 有关优化的更多信息 而不是能够完成前5次查询,对吗?如果是这种情况,那么也许还有其他选项使用WordPress API?
最好使用瞬态API进行缓存?
我认为您的帖子不会经常改变,对吗?如果您接受三(3)个查询,然后定期命中率,然后使用 瞬态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
过滤钩您可能是使用缓存与 瞬态API 反而。
希望这可以帮助?
其他提示
WP_Query()
不支持类似 每个猫的第一个X. 。代替 WP_Query()
您可以使用 get_posts()
在您的每个类别上,可以说三遍:
<?php
$posts = array():
$categories = array(2,4,8);
foreach($categories as $cat) {
$posts[] = get_posts('numberposts=5&offset=1&category='.$cat);
}
?>
$posts
现在包含每个类别的前五个帖子。
我不知道一种方法可以在单个查询中获取每个类别的前五个帖子。如果您只有45个帖子,那么一次访问数据库并为每个类别获取五个帖子可能是最有效的方法。击中数据库三次并结合结果并不是一件坏事。