Pre_Get_Posts Order By Not Working

时间:2016-02-22 作者:Michael

我正在使用pre_get_posts 钩子在查询运行之前更改查询。

所讨论的职位是绩效,因此是基于日期和时间的。

我想更改查询以获取将来的所有性能(即日期大于今天或日期为今天且时间大于或等于当前时间)。这是可行的,但当我试图主要按日期升序,其次按时间升序排序时,顺序并不像预期的那样。

这些帖子是按日期正确排序的,但只有今天的表演是按时间正确排序的,其他日子的表演时间是随机排序的。

我认为这与相对于orderby参数的meta\\u查询数组的命名有关,但无法解决此问题。

我的代码如下:

    //No limit on number to get
    $query->set(\'posts_per_page\', -1);
    //Get future performances
    $query->set(\'meta_query\', array(
        \'relation\'  => \'AND\',   
        array(
            \'relation\'  => \'OR\',
            \'performance_date\' => array(
                \'key\' => \'performance_date\', 
                \'value\' => date(\'Ymd\'),
                \'compare\' => \'>\',
                \'type\' => \'NUMERIC\'
            ),
            array(
                \'relation\'  => \'AND\',
                \'performance_date\' => array(
                    \'key\' => \'performance_date\', 
                    \'value\' => date(\'Ymd\'),
                    \'compare\' => \'=\',
                    \'type\' => \'NUMERIC\'
                ),                      
                \'performance_time\' => array(
                    \'key\' => \'performance_time\', 
                    \'value\' => date(\'H:i\'),
                    \'compare\' => \'>=\',
                    \'type\' => \'TIME\'
                )
            )               
        )
    ));
    //Order by closest performance first
    $query->set(\'orderby\', array(
        \'performance_date\' => \'ASC\',
        \'performance_time\' => \'ASC\'
    )); 

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

我想如果你有performance_datetime 自定义字段,因为这样可以简化元查询。

以下只是一个有趣的演示:

据我所知,在wp_posts 表,即wp_postmeta, mt1mt2. 但是meta_key 对于这些联接的表,字段并不总是performance_dateperformance_time. 因此,在其中一个表中,按meta值排序对于WP_Query.

仅在这种情况下,硬编码的解决方法可以是:

ORDER BY 
   CASE
        WHEN wp_postmeta.meta_key = \'performance_date\' 
            THEN CAST( wp_postmeta.meta_value AS SIGNED )
        WHEN mt1.meta_key = \'performance_date\' 
            THEN CAST( mt1.meta_value AS SIGNED )
        WHEN mt2.meta_key = \'performance_date\' 
            THEN CAST( mt2.meta_value AS SIGNED )
        ELSE
            wp_postmeta.post_id
    END ASC,
    CASE
        WHEN wp_postmeta.meta_key = \'performance_time\' 
            THEN CAST( wp_postmeta.meta_value AS TIME)
        WHEN mt1.meta_key = \'performance_time\' 
            THEN CAST( mt1.meta_value AS TIME)
        WHEN mt2.meta_key = \'performance_time\' 
            THEN CAST( mt2.meta_value AS TIME)
        ELSE
            wp_postmeta.post_id
    END ASC
您可以通过以下方式进行测试:

$query->set(\'orderby\', \'performance\' );
以下未测试插件支持自定义排序:

add_filter( \'posts_orderby\', function( $orderby, \\WP_Query $q )
{
    if( \'performance\' !== $q->get( \'orderby\' ) )
        return $orderby;

    global $wpdb;

    $order = ( \'ASC\' === strtoupper( $q->get( \'order\' ) ) ) ? \'ASC\' : \'DESC\';
    $orderby = "
       CASE
            WHEN {$wpdb->postmeta}.meta_key = \'performance_date\' 
                THEN CAST( {$wpdb->postmeta}.meta_value AS SIGNED )
            WHEN mt1.meta_key = \'performance_date\' 
                THEN CAST( mt1.meta_value AS SIGNED )
            WHEN mt2.meta_key = \'performance_date\' 
                THEN CAST( mt2.meta_value AS SIGNED )
            ELSE
                {$wpdb->postmeta}.post_id
       END {$order},
       CASE
            WHEN {$wpdb->postmeta}.meta_key = \'performance_time\' 
                THEN CAST( {$wpdb->postmeta}.meta_value AS TIME)
            WHEN mt1.meta_key = \'performance_time\' 
                THEN CAST( mt1.meta_value AS TIME)
            WHEN mt2.meta_key = \'performance_time\' 
                THEN CAST( mt2.meta_value AS TIME)
            ELSE
                {$wpdb->postmeta}.post_id
        END {$order}";

    return $orderby;
}, 10, 2 );
请注意,这是相当不灵活的,因为当您更改查询时,这可能不起作用。但希望您可以根据自己的需要进行调整,甚至使其更加灵活。

相关推荐

如何在WooCommerce_Account_Orders函数中传递$CURRENT_PAGE?

woocommerce功能woocommerce_account_orders($current_page) 已调用1个参数$current_page. 该函数通过调用woocommerce_account_orders_endpoint 通过以下挂钩-add_action( \'woocommerce_account_orders_endpoint\', \'woocommerce_account_orders\' );然而,在上述挂钩中,$current_page 未在函数中作为参数传递。情况如何$c