WordPress按总分和最接近的数字排序

时间:2017-10-31 10:07:32

标签: php wordpress

我正在开发一个WordPress插件,其中团队的总分应为orderby,而第二个参数最接近表中的随机数。

所以我们可以说有三支球队的总得分相似,我们需要找出谁在这轮比赛中表现最佳。因此,首先每个人都猜测一个随机数,例如:301020。

  • 第1组猜测:300000。距离正确答案1020
  • 团队2猜测:28000。273020远离正确答案
  • 第三队猜测:302000。980远离正确答案

所以第3队应该排在首位,因为他们最接近正确答案。

这就是我目前的情况:

new WP_Query( array(
      'post_type'       => 'team',
      'posts_per_page'  => -1,
      'order'           => 'DESC',
      'meta_key'        => 'total_score',
      'meta_query'      => array(
         'relation'     => 'AND',
         array(
            'key'       => 'total_score',
            'value'     => '0',
            'compare'   => '>',
            'type'      => 'numeric'
         ),
         'entry_round'  => array(
            'relation'  => 'OR',
            array(
               'key'       => 'round_entry',
               'value'     => 301020,
               'type'      => 'numeric',
               'compare'   => '>='
            ),
            array(
               'key'       => 'round_entry',
               'value'     => 301020,
               'type'      => 'numeric',
               'compare'   => '<='
            )
         ),
      ),
      'orderby'         => array(
         'entry_round'  => 'DESC'
      )
   ));

1 个答案:

答案 0 :(得分:2)

我想我明白你的目标是什么,而且只使用带有参数数组的WP_Query是不可能的。

幸运的是,WP提供了过滤器来操作WP_Query用来查找帖子的自动生成的SQL。

这应该有用,我相信:

$randomNumber = 301020;
function orderby_closest($orderby) {
    global $randomNumber;
    return "wp_postmeta.meta_value DESC, ABS(mt1.meta_value - $randomNumber) ASC";
}

add_filter("posts_orderby", "orderby_closest", 10, 1);

$info = new WP_Query( array(
    'post_type'       => 'team',
    'posts_per_page'  => -1,
    'meta_query'      => array(
        'relation'     => 'AND',
        array(
            'key'       => 'total_score',
            'value'     => '0',
            'compare'   => '>',
            'type'      => 'numeric'
        ),
        array(
            'key'       => 'round_entry',
            'compare'   => 'EXISTS'
        ),
    ),
));
remove_filter("posts_orderby", "orderby_closest");

print $info->request;

我已删除了round_entry上的条件,因为它们无关紧要,我们只需要为该字段进行连接(因此我们可以使用它们ORDER BY表达式),我们可以通过对compare使用“EXISTS”来强制执行此操作。 orderorderby已被删除,因为我们会照顾好自己。魔术发生在函数orderby_closest中,该函数与内置的posts_orderby过滤器一起使用,该过滤器专为此类场合而设计,您希望在将SQL发送到数据库之前对其进行更改。

至于orderby_closest的返回值,这非常简单: 通过total_score的第一个顺序,然后ABS将返回数字的绝对值,基本上从减法的结果中剥离数学符号(对于我们的目的,这正是猜测和随机数之间的距离)。 mt1.meta_value是元字段round_entry的值(如果更改meta_query entires的顺序,则必须对此进行调整)。我们将按升序排序,因为您希望与随机数差别最小的那些位于顶部。

print $info->request输出生成的SQL,类似于

SELECT wp_posts.* FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) INNER JOIN wp_postmeta AS mt1 ON ( wp_posts.ID = mt1.post_id ) WHERE 1=1 AND ( ( wp_postmeta.meta_key = 'total_score' AND CAST(wp_postmeta.meta_value AS SIGNED) > '0' ) AND mt1.meta_key = 'round_entry' ) AND wp_posts.post_type = 'team' AND (wp_posts.post_status = 'publish') GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value DESC, ABS(mt1.meta_value - 301020) ASC

Et瞧,我们有一个幸运的赢家(或获胜者)。