it-swarm.cn

使用WP_Query查询每个类别有限帖子的多个类别?

我有3个类别,每15个帖子,我想对数据库做一个查询,每个类别只带5个第一帖子,我该怎么办?

$q = new WP_Query(array( 'post__in' => array(2,4,8), 'posts_per_page' => **FIRST_5_OF_EACH_CAT** ));

如果它不可能,什么是更有效,获取父类别的所有帖子并循环它们或创建3个不同的查询?

10
Amit

您想要的是什么,但是需要您深入研究 我希望尽可能避免的SQL (不是因为我不知道它,我是一个先进的SQL开发人员,但因为 in WordPress您希望尽可能使用API​​ 以最大限度地减少与未来潜在数据库结构更改相关的未来兼容性问题。)

带有UNION运算符的SQL是一种可能性

要使用SQL,你需要的是一个UNION运算符在你的查询中,假设你的类别slugs是"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;是左齐。另请注意,我使用全局变量来允许您通过在数组中列出类别slugs来定义钩子之外的类别。您可以将此代码放在插件中或主题的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次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);

摘要

虽然是的,你可以做你所要求的使用SQL UNION查询和posts_join过滤器钩子,你可能更好地提供使用Transients API的缓存。

希望这可以帮助?

15
MikeSchinkel

WP_Query()不支持像 First X For Each Cat 。而不是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现在包含每个类别的前五个帖子。

1
hakre

我不知道如何在单个查询中获得每个类别的前五个帖子。如果您将只有45个帖子,那么点击数据库一次并获得每个类别的5个帖子可能是最有效的方法。虽然击中数据库三次并结合结果并不是一件坏事。

0
Bernard Chen