WordPress日期查询返回误报

时间:2014-06-06 10:59:01

标签: php sql wordpress date

我有一个复杂的wp_query正在进行一个新的网站,它会根据日期参数返回一些误报。

我希望用户能够根据开始和结束日期搜索事件。每个事件可以有多个“周期”(例如,冬季和夏季)。

句点在ACF转发器字段中设置,因此在数据库中它看起来像这样:

期间1:date_0_start-date / date_0_end-date
第2期:date_1_start-date / date_1_end-date
第3期:date_2_start-date / date_2_end-date
等...

如果只有一个句点,则查询正常。但是,如果有多个句点,则事件几乎总会显示,即使它们超出了用户搜索范围。

这是wp_query:

$args = array(  
    // general
    'post__in' => $postIDs,
    'post_type' => 'event',
    'posts_per_page' => 10,
    'paged' => $paged,

    'meta_key' => $_SESSION['search']['sort-key'],
    'orderby' => $_SESSION['search']['sort-by'],
    'order' => 'ASC',

    // category filter
    'tax_query' => $taxQuery,

    // date filter
    'meta_query' => array(
        'relation' => 'AND',
        array(
            'key' => 'date_%_start-date',
            'value' => $when,
            'compare' => '>=',
            'type' => 'NUMERIC'
        ),
        array (
            'key' => 'date_%_end-date',
            'value' => $when2,
            'compare' => '<=',
            'type' => 'NUMERIC'
        )
    )


);

我还在查询之前添加了这些函数,以稍微更改它以允许查询中的%变量:

function date_to( $to ) {
    $to = str_replace("mt1.meta_key = 'date_%_end-date'", "mt1.meta_key LIKE 'date_%_end-date'", $to);
    return $to;
}

function date_from( $from ) {
    $from = str_replace("meta_key = 'date_%_start-date'", "meta_key LIKE 'date_%_start-date'", $from);
    return $from;
}

但是,它不会检查%变量是否匹配,因此它可以从第1期获得开始日期,从第2期获得结束日期,并使其与用户查询匹配。

我是如何改进这一点以使其在多个时期更加健壮的任何想法?

[编辑] SQL查询中的请求。

SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID 
FROM wp_posts  
INNER JOIN wp_term_relationships 
ON (wp_posts.ID = wp_term_relationships.object_id) 
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_posts.ID 
IN (1033,1039, ... more numbers ... 1264) 
AND ( wp_term_relationships.term_taxonomy_id IN (3) ) 
AND wp_posts.post_type = 'event' 
AND (wp_posts.post_status = 'publish' 
OR wp_posts.post_status = 'private') 
AND ( (wp_postmeta.meta_key LIKE 'date_%_start-date' AND CAST(wp_postmeta.meta_value AS SIGNED) >= '20131201')
AND  (mt1.meta_key LIKE 'date_%_end-date' AND CAST(mt1.meta_value AS SIGNED) <= '20150101') ) 
GROUP BY wp_posts.ID 
ORDER BY FIELD( wp_posts.ID, 1033,1039, ... more numbers ... 1264 ) 
LIMIT 0, 10

[编辑]

根据以下答案更新了代码,但仍然不太合适。

新功能:

function add_additional_where_condition( $wp_query) {
    $wp_query = str_replace("WHERE", "WHERE substr(wp_postmeta.meta_key, 1, 6) = substr(mt1.meta_key, 1, 6) AND ", $wp_query);
    return $wp_query;
}

添加:
add_filter('posts_where', 'add_additional_where_condition');

SQL返回:

SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID 
FROM wp_posts  
INNER JOIN wp_term_relationships 
ON (wp_posts.ID = wp_term_relationships.object_id) 
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)
INNER JOIN wp_postmeta AS mt2 
ON (wp_posts.ID = mt2.post_id) 
WHERE 1=1  AND wp_posts.ID IN (503,475,529,473,469) 
AND ( wp_term_relationships.term_taxonomy_id IN (2) ) 
AND wp_posts.post_type = 'event' 
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') 
AND (wp_postmeta.meta_key LIKE 'date_%_start-date'
AND  (mt1.meta_key LIKE 'date_%_start-date' AND CAST(mt1.meta_value AS SIGNED) >= '20140611')
AND  (mt2.meta_key LIKE 'date_%_end-date' AND CAST(mt2.meta_value AS SIGNED) <= '20140618') ) 
GROUP BY wp_posts.ID 
ORDER BY wp_postmeta.meta_value 
ASC LIMIT 0, 10

2 个答案:

答案 0 :(得分:1)

我认为你所寻找的并不容易实现。

您需要的是:

AND ( (wp_postmeta.meta_key LIKE 'date_%_start-date' AND CAST(wp_postmeta.meta_value AS SIGNED) >= '20131201')
AND  (mt1.meta_key LIKE 'date_%_end-date' AND CAST(mt1.meta_value AS SIGNED) <= '20150101') ) 

AND substr(wp_postmeta.meta_key, 1, 6) = substr(mt1.meta_key, 1, 6)

因此,正确的开始日期将与正确的结束日期一起使用。

您可以包含一个附加函数,该函数将在WHERE子句的开头添加此条件:

function add_additional_where_condition( $where) {
    $where .= " AND substr(wp_postmeta.meta_key, 1, 6) = substr(mt1.meta_key, 1, 6) ";
    return $where;
}

两个substr()应返回相同的date_#值。

希望这可以提供帮助。

答案 1 :(得分:0)

您需要更改type中的meta_query

Documents说: -

type (string) -> Custom field type.

Possible values are:- 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME',
'UNSIGNED'. Default value is 'CHAR'.

所以请尝试以下代码: -

'meta_query' => array(
            'relation' => 'AND',
            array(
                    'key' => 'date_%_start-date',
                    'value' => $when,
                    'compare' => '>=',
                    'type' => 'DATE'
            ),
            array (
                    'key' => 'date_%_end-date',
                    'value' => $when2,
                    'compare' => '<=',
                    'type' => 'DATE'
            )
    )

尝试根据 type 更改(eg. Date) Custom Fild type

希望这会对你有所帮助。