我有一个复杂的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
答案 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
。
希望这会对你有所帮助。