获取帖子在类别中的位置

时间:2014-02-01 作者:Shazzad

我有一个帖子id x,一个类别id y。我想检索帖子在类别中出现的位置。

确认该帖子来自类别,帖子顺序将基于post meta中设置的数值,meta键“facebook\\u shares”类别有超过1k个其他帖子我正在寻找一种最佳的解决方案,它可以减少数据库查询使用量,并且单个查询将是最好的。

提前谢谢。

1 个回复
最合适的回答,由SO网友:gmazzap 整理而成

如果我理解的很好,你需要检索所有类别为“y”的帖子以及元键“facebook\\u共享”,然后,你需要特定帖子的位置。

我的建议是:

创建一个扩展WP_Query 并过滤所需类别和元字段的结果。此类还应过滤SQL查询,以将元值设置为返回的post对象的属性WP_Query::get_postsSpl ArrayIterator 迭代所有帖子并将每个帖子放入SplHeap 实现compare 方法查看post对象的元属性。SplHeap具有自动排序元素的属性,这些元素在其中传递并插入only one db查询完成。

让我们来编码。

首先写下我们的SplHeap 实施:

class SharesHeap extends SplHeap {  
  public function compare( $post1, $post2 ) {
    $key = FB_Shares_Query::$key;
    if ( ! $post1 instanceof WP_Post || ! isset( $post1->$key ) ) return 0;
    if ( ! $post2 instanceof WP_Post || ! isset( $post2->$key ) ) return 0;
    return (int)$post2->$key - (int) $post1->$key;
  }
}
现在扩展的类WP_Query 来获取帖子。此类的构造函数接受一个类别术语,该术语可以作为类别id、类别slug甚至类别对象传递。默认情况下\'post_type\' 参数设置为“post”,但可以通过向构造函数传递第二个参数来覆盖该参数。

class FB_Shares_Query extends WP_Query {

  public static $key = \'facebook_shares\'; // change the metakey here, if needed
  protected static $args = array( \'nopaging\' => TRUE ); // get all posts

  public function __construct( $cat = NULL, $post_type = \'post\' ) {
    if ( is_object($cat) && isset($cat->term_id) ) $cat = $cat->term_id;
    $cat_field = is_numeric($cat) ? \'cat\' : \'category_name\';
    self::$args[\'post_type\'] = ! empty( $post_type ) ? $post_type : \'post\';
    self::$args[$cat_field] = $cat;
    parent::__construct( self::$args );
  }

  public function get_posts() {
    add_filter(\'posts_clauses\', array(__CLASS__, \'my_filters\') );
    $results = parent::get_posts();
    remove_filter(\'posts_clauses\', array(__CLASS__, \'my_filters\') );
    return $results;
  }

  public static function my_filters( $pieces ) {
    $key = self::$key;
    $meta = $GLOBALS[\'wpdb\']->postmeta;
    $posts = $GLOBALS[\'wpdb\']->posts;
    $pieces[\'fields\'] .= ", {$meta}.meta_value as {$key}";
    $pieces[\'join\'] .= "INNER JOIN {$meta} ON ({$posts}.ID = {$meta}.post_id)";
    $where = " AND ( {$meta}.meta_key = \'{$key}\' AND ";
    $where .= " CAST( {$meta}.meta_value AS SIGNED ) > 0 )";
    $pieces[\'where\'] .= $where;
    return $pieces;
  }
}
然后是“粘合”上一个类:

class FB_Shares_Order {

  protected $heap;
  protected $posts;

  public function __construct( SplHeap $heap )  {
    $this->heap =  $heap;
  }

  public function getOrder( WP_Post $post = NULL ) {
    if ( ! $this->posts instanceof ArrayIterator ) return -1;
    if ( ! isset( $post->ID ) ) return FALSE; 
    while( $this->posts->valid() ) {
      $this->heap->insert( $this->posts->current() );
      $this->posts->next();
    }
    $position = 0;
    while( $this->heap->valid() ) {
      $current = $this->heap->extract();
      if ( $current->ID == $post->ID ) return $position + 1;
      $position++;
    }
    return FALSE;
  }

  public function getPosts( WP_Query $query ) {
    if ( $query->post_count > 0) $this->posts = new ArrayIterator( $query->posts );
  }
}
最后,一个函数façade 到3个班级。它接受post(id或object)和category(id、slug或object):

function getFB_Shares_Order( $post, $cat ) {
  if ( is_object($post) && isset( $post->ID ) ) $post = $post->ID;
  if ( ! is_numeric($post) || ! (int) $post > 0 ) return FALSE;
  if ( ! has_category($cat, $post) ) return FALSE;
  $order = new FB_Shares_Order( new SharesHeap );
  $order->getPosts( new FB_Shares_Query( $cat ) );
  return $order->getOrder( get_post( $post ) );
}
用法示例
global $post;
$position = getFB_Shares_Order( $post, \'uncategorized\' );
返回值:如果查询返回一些帖子,并且给出的帖子是其中之一,那么函数将返回帖子集合中的帖子顺序,查看“facebook\\u shares”元键。

E、 G.查询返回3篇帖子,分别值为“facebook\\u shares”:10、15、30,将“facebook\\u shares”为15的帖子id传递给函数,然后函数返回2, 因为这个职位是第二顺位的。

如果查询未返回POST,则函数返回-1.

如果查询返回一些帖子,但其中不存在想要的帖子,则函数返回false.

注意事项

使用没有特定值的meta\\u查询进行核心WP\\u查询时存在一些问题(\'compare\'=存在或不存在),特别是当查询还包含税务查询时。为了避免它们,在扩展WP-query的类中,对SQL查询使用一些过滤器,并且where子句是“手动”设置的。但是,如果有一些外部代码(插件、主题)在查询中添加自定义过滤器(使用posts\\u where、posts\\u join和类似的过滤器挂钩),那么这些代码可能会破坏调用行为。

该代码经过了快速测试,但似乎很有效。。无保修。

结束

相关推荐

从2种不同的帖子类型中查询连接的帖子(使用posts2post)

假设我有3种帖子类型:帖子、议程和慈善。我使用插件Posts2posts 从scribu将某些帖子和某些议程项目连接到一些慈善项目。在慈善机构的单页上,我想在侧栏中显示帖子和议程。我有两个问题:1st problem: 我要混合,但仍按日期分类2nd problem: 我只想显示与我的慈善帖子相关的帖子和议程项目。看起来像是-连接到此慈善机构的最后一个帖子-与该慈善机构相关的最后一个议程项目-Forlast post item连接到此慈善机构-与该慈善机构相关的最后一个议程项目当使用wp\\u query