如果我理解的很好,你需要检索所有类别为“y”的帖子以及元键“facebook\\u共享”,然后,你需要特定帖子的位置。
我的建议是:
创建一个扩展WP_Query
并过滤所需类别和元字段的结果。此类还应过滤SQL查询,以将元值设置为返回的post对象的属性WP_Query::get_posts
李安Spl 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和类似的过滤器挂钩),那么这些代码可能会破坏调用行为。
该代码经过了快速测试,但似乎很有效。。无保修。