对多个键和比较值使用META_QUERY

时间:2014-11-21 作者:indextwo

我想我可能是在用这根棍子乞求月亮,但是:

我有一个过滤器shows 自定义帖子类型。过滤器使用附加到的标准分类法shows, 但也允许用户按场馆过滤,这是每个节目的元值,或者按月份过滤,因为每个节目都附有开始日期。

我遇到的问题是,一些节目可能会跨越几个月;因此,2014年11月开始跑步,12月结束。为此,我将元数据存储如下:

startdate   => 20141225
enddate     => 20141224
理想情况下,如果有人筛选2014年12月的节目,我希望显示12月内开始、12月底之前结束的节目。问题是,因为我也在检查venue meta\\u值relation => \'AND\', 我想不出一种方法来检查伪代码WHERE venue == \'royal-playhouse\' AND ((startdate BETWEEN array(20141201, 20141231)) OR (enddate BETWEEN array(20141201, 20141231))).

我用的是pre_get_posts 筛选器以修改通过的$query 参数,值得注意的是,还有几个meta\\u值字段也与过滤器一起使用(例如显示类型、可访问性等)。这是我的代码的简化版本(目前运行良好,但只检查startdate):

function showDates_orderQuery($query) {
    if ($query->is_main_query() && !is_admin() && is_post_type_archive(\'showdates\')) {

        $queryVenue = $query->query_vars[\'venue\'];
        $queryMonth = $query->query_vars[\'month\'];

        $metaQuery = array();

        //  Venue meta

        if ($queryVenue) {
            $metaQuery[] = array(
                \'key\'       => \'venue\',
                \'value\'     => array($queryVenue),
                \'compare\'   => \'IN\',
            );
        }

        //  Month meta

        if ($queryMonth) {

            $monthEpoch = strtotime($queryMonth);
            $formattedQueryMonth = date(\'Ymd\', $monthEpoch);
            $formattedEndOfQueryMonth = date(\'Ymt\', $monthEpoch);

            $metaQuery[\'relation\'] = \'AND\'; //  Set because we want to check for shows from a venue AND by the given month

            $metaQuery[] = array(
                \'key\'       => \'startdate\',
                \'value\'     => array($formattedQueryMonth, $formattedEndOfQueryMonth),
                \'compare\'   => \'BETWEEN\',
                \'type\'      => \'DATE\'
            );
        }

        if ($metaQuery) {
            $query->set(\'meta_query\', $metaQuery);
        }

        $query->set(\'meta_key\', \'startdate\');
        $query->set(\'orderby\', \'meta_value\');
        $query->set(\'order\', \'ASC\');
    }
}

add_action(\'pre_get_posts\', \'showDates_orderQuery\');
如果您有任何关于如何实现这一目标的想法,我将不胜感激。

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

因为我是个十足的白痴,我似乎完全忘记了我basically answered my own question over a year ago.

我在努力获得posts_join 过滤器的行为(我通常有问题INNER JOIN,因此posts_where 滤器它的主要问题是,除了现有的$where 条件在这个例子中,我希望它使用非全局变量。

答案是对posts_where 过滤器:

if ($queryMonth) {

    $monthEpoch = strtotime($queryMonth);
    $formattedQueryMonth = date(\'Ymd\', $monthEpoch);
    $formattedEndOfQueryMonth = date(\'Ymt\', $monthEpoch);

    $monthOptions = array(
        \'monthstart\' => $formattedQueryMonth,
        \'monthend\' => $formattedEndOfQueryMonth,
    );

    $monthFilter = function ($where = \'\') use ($monthOptions) {
        global $wpdb;
        $where .= " AND (($wpdb->postmeta.meta_key = \'startdate\' AND $wpdb->postmeta.meta_value >= \'" . $monthOptions[\'monthstart\'] . "\') AND ($wpdb->postmeta.meta_key = \'startdate\' AND $wpdb->postmeta.meta_value <= \'" . $monthOptions[\'monthend\'] . "\')) ";
        $where .= " OR (($wpdb->postmeta.meta_key = \'enddate\' AND $wpdb->postmeta.meta_value >= \'" . $monthOptions[\'monthstart\'] . "\') AND ($wpdb->postmeta.meta_key = \'enddate\' AND $wpdb->postmeta.meta_value <= \'" . $monthOptions[\'monthend\'] . "\')) ";
        return $where;
    };

    add_filter(\'posts_where\', $monthFilter);
}
幸运的是,由于forthcoming release of 4.1 - 感谢@jmusalheads up.

SO网友:jmusal

根据您的时间安排或您希望生活在边缘的程度,我认为4.1将引入一些伟大的改进,这些改进将允许您完成您想要做的事情。如果你想在边缘生活一点,你可以使用4.1测试版进行开发,并在发布时切换到该版本(如果找到bug报告,请务必提交:))

下面是一个链接,指向更详细的make post:https://make.wordpress.org/core/2014/10/20/update-on-query-improvements-in-4-1/

SO网友:Otto

你想不出一个方法来做到这一点,因为没有这样的方法。像这样将and和OR与meta\\u查询混合使用是不可能的。查询系统很好,但并不全面。您需要使用多个查询,或者自己过滤SQL。

结束

相关推荐

使用新的WP-Query()从循环中过滤后期格式;

嗨,我目前正在为我的博客构建一个主题。下面的代码指向最新的帖子(特色帖子)。因为这将有一个不同的风格比所有其他职位。然而我想过滤掉帖子格式:链接使用我在循环中定义的WP查询,因为它给我带来了更多的灵活性。我该怎么做呢? <?php $featured = new WP_Query(); $featured->query(\'showposts=1\'); ?> <?php while ($featured->have_post