对具有多个后元日期字段的帖子进行排序

时间:2014-12-05 作者:Mikko Siikaniemi

你好WordPress开发人员。多年来,我在WordPress中找到了许多问题的答案。我想感谢你的帮助。今天,我自己有一个问题,寻求专家的建议。

我正在建一个电影院的场地。我有一个自定义的帖子类型movies. 我正在使用Types 插件将每部电影的放映日期和时间存储为重复的日期/时间字段。它将日期/时间作为Unix时间戳存储到带有meta\\u键“wpcf showtime”的Posteta表中。每部电影都有许多放映时间,因此有许多meta\\u键/meta\\u值对具有相同的键,例如:。

post\\u id:70,meta\\u key:wpcf showtime,meta\\u value 1417548600,post\\u id:70,meta\\u key:wpcf showtime,meta\\u value 1417813200,post\\u id:70,meta\\u key:wpcf showtime,meta\\u value 1417896000

对于该网站的首页,我想显示下周周三之前的所有正在播放的电影,即从现在开始有放映时间的电影,不包括过去或标记为未来的电影(自定义分类法)。

我的问题是订购电影;我想按放映时间顺序放映,这样一来,放映时间最接近当前时间的电影就会排在第一位。

这是我正在运行的查询:

$startdate = time();
$enddate = new DateTime(\'thursday next week\');

$ongoing_movies = new WP_Query( array( 
    \'post_type\' => \'movies\',
    \'meta_key\'  => \'wpcf-showtime\',
    \'orderby\'   => \'meta_value_num\', 
    \'order\'     => \'ASC\',
    \'tax_query\' => array(
        array(
            \'taxonomy\' => \'genre\',
            \'field\'    => \'slug\',
            \'terms\'    => \'future\', 
            \'operator\' => \'NOT IN\'
        )
    ),
    \'meta_query\' => array(
        array(
            \'key\'      => \'wpcf-showtime\',
            \'value\'    => array ( $startdate, $enddate->format(\'U\')),
            \'compare\'  => \'BETWEEN\', 
        ),
    )
));
这将返回按showtime排序的正确电影。但它用于排序的显示时间是为该特定电影存储的meta\\u键“wpcf showtime”的第一个值。一、 e.显示的第一部电影可能不是下一部电影,而是在db中存储了最早放映时间的电影。

如果有人能帮我找到解决办法,我将不胜感激;pre\\u get\\u posts操作,posts\\u orderby筛选器?

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

1) 仅使用posts_orderby 筛选器:

看起来您想按minimumwpcf-showtime 元值。

您可以修改ORDER BYWP_Query, 通过使用posts_orderby 滤器

下面是一个示例:

add_filter( \'posts_orderby\', \'wpse_posts_orderby\' );
$ongoing_movies = new WP_Query( $args );
其中,过滤器回调定义为:

/**
 *  Use MIN() on the meta value part ordering.
 */
function wpse_posts_orderby( $orderby )
{      
    global $wpdb;

    // Only run this callback once:
    remove_filter( current_filter(), __FUNCTION__ );

    // Replacement part:  
    $find    = "{$wpdb->postmeta}.meta_value+0 ";
    $replace = "mt1.meta_value+0 ";

    // Make sure we add MIN() to the correct part:    
    if( $find == str_ireplace( array( \'ASC\', \'DESC\' ), \'\', $orderby ) )
    {
        // Preserve the order direction:
        $orderby = str_ireplace(
            $find,
            "MIN( $replace) ",
            $orderby
        );
    }
    return $orderby;
}
这里我们使用mt1.meta_value, 如果元值限制是meta_query.

这将改变:

ORDER BY wp_postmeta.meta_value+0 {ASC|DESC}

ORDER BY MIN( mt1.meta_value+0 ) {ASC|DESC}
在中引入自定义订单参数WP_Query您可以尝试使用此设置:

$startdate = time();
$enddate = new DateTime(\'thursday next week\');

$ongoing_movies = new WP_Query( array( 
    \'post_type\'    => \'movies\',
    \'meta_key\'     => \'wpcf-showtime\',
    \'wpse_orderby\' => \'meta_value_num_min\',      // <-- New parameter to order by MIN!
    \'orderby\'      => \'meta_value_num\', 
    \'order\'        => \'ASC\',
    \'tax_query\'    => array(
        array(
            \'taxonomy\' => \'genre\',
            \'field\'    => \'slug\',
            \'terms\'    => \'future\', 
            \'operator\' => \'NOT IN\'
        )
    ),
    \'meta_query\' => array(
        array(
            \'key\'      => \'wpcf-showtime\',
            \'value\'    => array ( $startdate, $enddate->format(\'U\')),
            \'compare\'  => \'BETWEEN\', 
            \'type\'     => \'UNSIGNED\'     // <-- Let\'s override the default \'CHAR\'
        ),
    )
));
我们使用以下插件来支持wpse_orderby 参数:

<?php
/**
 * Plugin Name: Modify the WP_Query ordering to support MAX and MIN
 * Description: Possible values of \'wpse_orderby\' are  \'meta_value_num_{min,max}\'.
 * Plugin URI:  http://wordpress.stackexchange.com/a/173496/26350
 * Author:      Birgir Erlendsson (birgire)
 * Version:     0.0.2
 */ 

add_action( \'init\', function(){
    if( class_exists( \'WPSE_Modify_Ordering\' ) )
    {
        $o = new WPSE_Modify_Ordering;
        $o->init();
    }
});

class WPSE_Modify_Ordering
{
    private $type    = \'\';
    private $order   = \'\';
    private $orderby = \'\';

    public function init()
    {
        add_action( \'pre_get_posts\', array( $this, \'pre_get_posts\' ) );
    }

    public function pre_get_posts( WP_Query $q )
    {
        if( 
            in_array( 
                $q->get( \'wpse_orderby\' ), 
                array( \'meta_value_num_min\', \'meta_value_num_max\' ) 
            ) 
        )
        {
            $this->type = strtoupper( substr( $q->get( \'wpse_orderby\' ), -3 ) );
            $this->order = ( \'\' !== $q->get( \'order\' ) ) ? $q->get( \'order\' ) : \'ASC\';
            add_filter( \'posts_orderby\', array( $this, \'posts_orderby\' ) );
        }
    }

    public function posts_orderby( $orderby )
    {
        remove_filter( current_filter(), array( $this, __FUNCTION__ ) );
        return " {$this->type}( mt1.meta_value+0 ) " . $this->order;
    }

} // end class
Thewpse_orderby 参数重写本机orderby 参数它支持值meta_value_num_minmeta_value_num_max.

这里我们在mt1.meta_value, 因为元值限制是meta_query.

我们保留orderby 参数,将其用作fallback 如果上述插件已停用。

希望您可以根据自己的需要进一步修改。

SO网友:Jono Alderson

这是一个看似复杂的问题;特别是关于订购contextual 查询范围内的日期,当一个对象可能有多个日期时;传统上,排序和排序使用日期数组中的最小值,这通常会导致在查询特定日期范围时排序不正确。

作为参考,这里是我在自己的方法中使用的代码的主要部分:

// Wrap query in filters to modify behaviour
// ==============  
add_filter(\'posts_join_paged\',\'doty_custom_posts_join\');
add_filter(\'posts_orderby\',\'doty_custom_posts_orderby\');
$new_query = new WP_Query( $args );
remove_filter(\'posts_orderby\',\'doty_custom_posts_orderby\');
remove_filter(\'posts_join_paged\',\'doty_custom_posts_join\');

// Hooks into the \'WHERE\' component of the SQL query
// ==============
function doty_custom_posts_join($where) {
  global $wpdb,$query_dates;
  $start_date = (int)$query_dates[0]-86400;
  $where .= "LEFT JOIN (
        SELECT post_id,($start_date - MIN(meta_value)) as orderdate
        FROM $wpdb->postmeta
        WHERE meta_key = \'dates\'
        AND meta_value > $start_date 
        GROUP BY post_id) AS date_orders
        ON $wpdb->posts.ID = date_orders.post_id";
  return $where;
}

// Hooks into the \'ORDER BY\' component of the SQL query
// ==============
function doty_custom_posts_orderby($orderby) {
  $orderby = " date_orders.orderdate DESC";
  return $orderby;
}
它使用posts_join_pagesposts_orderby 更改WP生成SQL查询的方式,该查询是由正常的WP\\U查询函数生成的。具体而言,它:

从全局变量中获取范围的开始日期构建新的左联接以创建orderdate 变量,它是从数组中最近的日期中选择的,并继续检查这是否是将来的日期使用orderdate 变量排序键我意识到我已经花了大约6个小时把它拼凑在一起,它不是最干净的,但希望它在某个地方有一些价值。

结束

相关推荐

Orderby自定义元返回随机顺序

[由Roberthue回答-我是按meta\\u value排序,而不是按meta\\u value\\u num排序]我创建了一个WP\\U查询,它执行以下操作:通过元查询获取待售业务的列表,使用get\\u query\\u var从URL获取待售业务的订单。使用查询var中的排序顺序检查元查询,以确保销售项目处于活动状态。在大多数情况下,它是有效的。元查询正确区分了活动和非活动帖子,排序会上升和下降,只有一个问题。。。数据按降序排列如下:9999974900035000030000027000002