如何使用WP_QUERY从两个类别中获取帖子?

时间:2014-02-02 作者:user3205234

我正在使用WP\\u Query创建“最新帖子”&;\'我主页上的热门帖子部分。我试着从2个类别(9和11)中抽取5篇帖子,但它只会显示来自cat 9的帖子。

这是我用于“最新帖子”的php-

<ul>
        <?php 

        $cat = array(9,11);
        $showposts = 5;
        $paged = (get_query_var(\'paged\')) ? get_query_var(\'paged\') : 1;
        $args=array(
            \'category__in\' => $cat, 
            \'showposts\' => $showposts,
            \'paged\' => $paged,
            \'orderby\' => \'post_date\',
            \'order\' => \'DESC\',
            \'post_status\' => \'publish\',
           );

        $the_query = new WP_Query ( $args ); //the query


        $i = 0;while ($the_query->have_posts() ) : $the_query->the_post(); //start the loop
        ?>

        <?php
        if($i==0){ //Sets the output for the top post
        ?>  
            <li class="first-news">
                <div class="post-thumbnail"><a href="<?php the_permalink(); ?>"><?php the_post_thumbnail(350,187); ?></a></div>
                <h2 class="post-box-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
                <p class="post-meta"><span class="tie-date"><?php the_time(\'F jS, Y\') ?></span></p>
                <div class="entry"><?php the_excerpt(); ?></div>
                <div><a class="more-link" href="<?php the_permalink(); ?>">Read More »</a></div>

            </li>


        <?php
            $i++;
             } else { ?>

                <li class="other-news rar">
                <div class="post-thumbnail"><a href="<?php the_permalink(); ?>"><?php the_post_thumbnail(145,93); ?></a></div>
                <h3 class="post-box-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
                <p class="post-meta"><span class="tie-date"><?php the_time(\'F jS, Y\') ?></span></p>
           </li>

        <?php } endwhile; //end of the loop ?>
        <?php wp_reset_postdata(); // reset the query ?>
        </ul> 
有什么建议吗?

3 个回复
SO网友:gmazzap

根据我的经验,使用\'posts_*\' 过滤器(\'posts_request\', \'posts_where\'...) 结合str_replace / preg_replace 不可靠且不灵活:

不可靠,因为如果另一个过滤器修改使用其中一个过滤器,在更好的情况下会得到意外的结果,在最坏的情况下会出现SQL错误。

不灵活,因为更改参数(例如类别的“include\\u children”)或重用代码(例如3个术语而不是2个术语)需要大量工作。

此外,将代码调整为多站点兼容的代码需要手动编辑SQL。

因此,有时,如果evevn不是性能方面的最佳解决方案,那么更规范的方法就是最好的、更灵活的方法。

通过一些缓存技巧可以提高性能。。。

我的提议:

编写一个函数以供使用usort 要对来自不同查询的帖子进行排序(例如,每个学期一篇),请编写一个函数,在第一次运行时运行单独的查询、合并结果、排序、缓存并返回它们。在随后的请求中,只需返回缓存结果,即可在需要时处理缓存失效问题。首先,命令发布的函数:

function my_date_terms_posts_sort( Array $posts, $order = \'DESC\' ) {
  if ( ! empty( $posts ) ) {
    usort( $posts, function( WP_Post $a, WP_Post $b ) use ( $order ) {
      $at = (int) mysql2date( \'U\', $a->post_date );
      $bt = (int) mysql2date( \'U\', $b->post_date );
      $orders = strtoupper($order) === \'ASC\' ? array( 1, -1 ) : array( -1, 1 );
      return $at === $bt ? 0 : ( $at > $bt ) ? $orders[0] : $orders[1];
    } );
  }
  return $posts;
}
然后,获取非缓存结果的函数:

function my_fresh_terms_get_posts( $args, $terms, $tax_query_args = NULL ) {
  $posts = array();
  // we need to know at least the taxonomy
  if ( ! is_array( $tax_query_args ) || ! isset( $tax_query_args[\'taxonomy\'] ) ) return;
  // handle base tax_query
  $base_tax_query = isset( $args[\'tax_query\'] ) ? $args[\'tax_query\'] : array();
  // run a query for each term
  foreach ( $terms as $term ) {
    $term_tax_query = wp_parse_args( array(
      \'terms\' => array( $term ),
      \'field\' => is_numeric( $term ) ? \'term_id\' : \'slug\'
    ), $tax_query_args );
    $args[\'tax_query\'] = array_merge( $base_tax_query, array($term_tax_query) );
    $q = new WP_Query( $args ); 
    if ( $q->have_posts() ) {
      // merging retrieved posts in $posts array
      // preventing duplicates using ID as array keys
      $ids = wp_list_pluck( $q->posts, \'ID\' );
      $keyed = array_combine( $ids, array_values( $q->posts ) );
      $posts += $keyed;
    }
  }
  return $posts;
}
现在,检查缓存并返回它(如果可用)或返回非缓存结果的函数

function my_terms_get_posts( $args, $terms, $tax_query_args = NULL, $order = \'DESC\' ) {
  // we need to know at least the taxonomy
  if ( ! is_array( $tax_query_args ) || ! isset( $tax_query_args[\'taxonomy\'] ) ) return;
  $tax = $tax_query_args[\'taxonomy\'];
  // get cached  results
  $cached = get_transient( "my_terms_get_posts_{$tax}" );
  if ( ! empty( $cached ) ) return $cached;
  // no cached  results, get \'fresh\' posts
  $posts = my_fresh_terms_get_posts( $args, $terms, $tax_query_args );
  if ( ! empty($posts) ) {
    // order posts and cache them
    $posts = my_date_terms_posts_sort( $posts, $order );
    set_transient( "my_terms_get_posts_{$tax}",  $posts, DAY_IN_SECONDS );
  }
  return $posts;
}
Cache is auto-cleaned daily, 但是,每次添加或更新特定分类法的新帖子时,都可能使其无效。可以在上添加清理缓存功能\'set_object_terms\'

add_action( \'set_object_terms\', function( $object_id, $terms, $tt_ids, $taxonomy ) {
  $taxonomies = get_taxonomies( array( \'object_type\' => array(\'post\') ), \'names\' );
  if ( in_array( $taxonomy, (array) $taxonomies ) ) {
    delete_transient( "my_terms_get_posts_{$taxonomy}" );
  }
}, 10, 4 );

使用

// the number of post to retrieve for each term
// total of posts retrieved will be equat to this number x the number of terms passed
// to my_terms_get_posts function
$perterm = 5;

// first define general args:
$paged = ( get_query_var(\'paged\') ) ? get_query_var(\'paged\') : 1;
$args = array(
  \'posts_per_page\' => $perterm,
  \'paged\' => $paged,
);

// taxonomy args
$base_tax_args = array(
  \'taxonomy\' => \'category\'
);
$terms = array( 9, 11 ); // is also possible to use slugs

// get posts
$posts = my_terms_get_posts( $args, $terms, $base_tax_args );

// loop
if ( ! empty( $posts ) ) {
  foreach ( $posts as $_post ) {
    global $post;
    setup_postdata( $_post );
    //-------------------------> loop code goes here    
  }
  wp_reset_postdata();
}
函数足够灵活,可以使用复杂的查询,甚至可以查询其他分类:

E、 G。

$args = array(
  \'posts_per_page\' => $perterm,
  \'paged\' => $paged,
  \'post_status\' => \'publish\',
  \'tax_query\' => array(
     \'relation\' => \'AND\',
     array(
       \'taxonomy\' => \'another_taxonomy\',
       \'terms\' => array( \'foo\', \'bar\' ),
       \'field\' => \'id\'
     )
   )
);

$base_tax_args = array(
  \'taxonomy\' => \'category\',
  \'include_children\' => FALSE
);

$terms = array( \'a-category\', \'another-one\' );

$posts = my_terms_get_posts( $args, $terms, $base_tax_args );
这样,“tax\\u query”设置在$args 数组将与中的tax查询参数进行自动合并$base_tax_args, 对于$terms 大堆

也可以按升序订购帖子:

$posts = my_terms_get_posts( $args, $terms, $base_tax_args, \'ASC\' );
请注意:

重要提示:如果某些帖子属于传递给函数的帖子中的多个类别(例如,在OP案例中,某些帖子同时具有类别9和11),则检索到的帖子数量将不是预期的数量,因为函数将在代码需要PHP 5.3时返回该帖子

SO网友:Mayeenul Islam

根据Codex:

Show Posts From Several Categories (使用类别id显示具有这些类别的帖子)将是:

$query = new WP_Query( \'cat=9,11\' );

法典的分页参数表明,\'showposts\' 已弃用并替换为\'posts_per_page\'.

posts_per_pageint)-每页要显示的帖子数(可通过Version 2.1, 已替换showposts 参数)。

SO网友:s_ha_dum

你所问的几乎是这个问题的重复:How do I create my own nested meta_query using posts_where / posts_join?

正如@fischi所指出的,问题几乎可以肯定的是,结果来自于一个类别或另一个类别,并且在这两个类别的代表性相等之前达到了岗位限制。为了让这一切顺利进行,你需要一个工会。WP_Query 无法实现这种逻辑,但使用挂钩可以使其正常工作。

$cat = 9; // your first category
$showposts = 5; // actual results are twice this value
$paged = (get_query_var(\'paged\')) ? get_query_var(\'paged\') : 1;
$args=array(
  \'cat\' => $cat, 
  \'posts_per_page\' => $showposts,
  \'paged\' => $paged,
  \'orderby\' => \'post_date\',
  \'order\' => \'DESC\',
  \'post_status\' => \'publish\',
);

function create_cat_union($clauses) {
  remove_filter(\'posts_request\',\'create_cat_union\',1);
  $clauses = str_replace(\'SQL_CALC_FOUND_ROWS\',\'\',$clauses,$scfr);

  $scfr = (0 < $scfr) ? \'SQL_CALC_FOUND_ROWS\' : \'\';

  $pattern = \'wp_term_relationships.term_taxonomy_id IN \\(([0-9,]+)\\)\';
  $clause2 = preg_replace(\'|\'.$pattern.\'|\',\'wp_term_relationships.term_taxonomy_id IN (11)\',$clauses); // manipulate this

  return "SELECT {$scfr} u.* FROM (({$clauses}) UNION ({$clause2})) as u";
}
add_filter(\'posts_request\',\'create_cat_union\',1,2);

$the_query = new WP_Query ( $args ); //the query
var_dump($the_query->posts);
几点注意事项:WP_Query 将分析category参数并查找category子级UNION 将包括第9类的所有儿童。我did not 对第11类重复这种逻辑。如果需要该功能,可以参考WP_Query source 并重现效果。

结束

相关推荐

具有自定义分类的自定义帖子类型中的WP_DROPDOWN_CATEGORIES

我有一个自定义的帖子类型,它有自己的分类法,基本上“show Vinces”是帖子类型,Vincement regions是分类法。看到一个场馆无法在多个地区存在,我删除了默认的metta框,并使用wp_dropdown_categories(). 分类法项目正在输出并按我所希望的方式显示,但它们不会被提交,并且下拉列表在提交后不会保留所选内容。我已经尽我所能地查看原始metabox的各种属性,并尝试将这些属性应用到下拉列表中,但到目前为止,我没有任何乐趣。我看过一些various WPSE上的帖子和ha