WordPress中ACF Repeater日期范围筛选异常问题排查
解决ACF Repeater日期范围重叠筛选异常问题
需求:筛选WordPress文章中,ACF Repeater字段(包含date_from/date_to日期范围)任意子项与用户输入的日期范围存在重叠的文章。
当前异常情况:某文章的Repeater子项日期为2025.06.01-2025.06.15、2025.08.01-2025.08.15,当用户输入2025.06.20-2025.06.30时,该文章被错误筛选出来。
以下是之前尝试的两段无效代码:
第一段尝试代码
function blog_load_more() { add_filter('posts_where', 'my_posts_where'); function my_posts_where($where) { $where = str_replace("meta_key = 'date_ranges_$", "meta_key LIKE 'date_ranges_%", $where); return $where; } $user_date_from = isset($_POST['date_from']) ? sanitize_text_field($_POST['date_from']) : ''; $user_date_to = isset($_POST['date_to']) ? sanitize_text_field($_POST['date_to']) : ''; $args = array( 'post_type' => 'post', 'posts_per_page' => 6, 'suppress_filters' => false, 'meta_query' => [ 'relation' => 'AND', [ 'relation' => 'AND', [ 'key' => 'date_ranges_$_date_from', 'value' => $user_date_to, 'compare' => '<=', 'type' => 'DATE', ], [ 'key' => 'date_ranges_$_date_to', 'value' => $user_date_from, 'compare' => '>=', 'type' => 'DATE', ], ], ] ); $ajaxposts = new WP_Query($args); remove_filter('posts_where', 'my_posts_where'); $output = ''; if ($ajaxposts->have_posts()) { ob_start(); while ($ajaxposts->have_posts()) : $ajaxposts->the_post(); echo '<div>' . get_the_title() . '</div>'; ?> <?php endwhile; $output = ob_get_contents(); ob_end_clean(); } $result = [ 'html' => $output, ]; echo json_encode($result); exit; } add_action('wp_ajax_blog_load_more', 'blog_load_more'); add_action('wp_ajax_nopriv_blog_load_more', 'blog_load_more');
第二段尝试代码片段
'meta_query' => [ 'relation' => 'AND', [ 'relation' => 'AND', [ 'key' => 'date_ranges_$_date_from', 'value' => array( $user_date_from, $user_date_to ), 'compare' => 'BETWEEN', 'type' => 'DATE', ], [ 'key' => 'date_ranges_$_date_to', 'value' => array( $user_date_from, $user_date_to ), 'compare' => 'BETWEEN', 'type' => 'DATE', ], ],
错误原因分析
- 字段匹配逻辑错误:原代码的
meta_query使用AND关系,但未确保date_ranges_$_date_from和date_ranges_$_date_to属于Repeater的同一个子项。数据库会将任意子项的date_from和另一个子项的date_to进行匹配,导致错误触发条件。 - 日期重叠逻辑错误:原代码的条件只判断了“文章的所有子项起始日期≤用户结束日期,且所有子项结束日期≥用户起始日期”,这不符合“任意子项与用户范围重叠”的需求。
正确解决方案
要实现“任意Repeater子项日期范围与用户输入范围重叠”,需满足以下日期重叠逻辑:
子项起始日期 ≤ 用户结束日期 且 子项结束日期 ≥ 用户起始日期
同时必须确保这两个条件针对Repeater的同一个子项。以下是修正后的代码:
function blog_load_more() { global $wpdb; $user_date_from = isset($_POST['date_from']) ? sanitize_text_field($_POST['date_from']) : ''; $user_date_to = isset($_POST['date_to']) ? sanitize_text_field($_POST['date_to']) : ''; // 空值处理 if (empty($user_date_from) || empty($user_date_to)) { $result = ['html' => '']; echo json_encode($result); exit; } // 转换为MySQL日期格式(确保用户输入是YYYY-MM-DD,若不是需先转换) $user_date_from = date('Y-m-d', strtotime($user_date_from)); $user_date_to = date('Y-m-d', strtotime($user_date_to)); // 自定义查询:关联同一个Repeater子项的date_from和date_to $post_ids = $wpdb->get_col($wpdb->prepare(" SELECT DISTINCT p.ID FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} mf ON p.ID = mf.post_id JOIN {$wpdb->postmeta} mt ON p.ID = mt.post_id WHERE p.post_type = 'post' AND p.post_status = 'publish' AND mf.meta_key LIKE 'date_ranges_%_date_from' AND mt.meta_key = REPLACE(mf.meta_key, '_date_from', '_date_to') AND mf.meta_value <= %s AND mt.meta_value >= %s ", $user_date_to, $user_date_from)); $args = [ 'post_type' => 'post', 'posts_per_page' => 6, 'post__in' => $post_ids ?: [0], // 空数组时传入[0]避免查询所有文章 'post_status' => 'publish' ]; $ajaxposts = new WP_Query($args); $output = ''; if ($ajaxposts->have_posts()) { ob_start(); while ($ajaxposts->have_posts()) : $ajaxposts->the_post(); echo '<div>' . get_the_title() . '</div>'; endwhile; $output = ob_get_contents(); ob_end_clean(); } wp_reset_postdata(); $result = ['html' => $output]; echo json_encode($result); exit; } add_action('wp_ajax_blog_load_more', 'blog_load_more'); add_action('wp_ajax_nopriv_blog_load_more', 'blog_load_more');
代码说明
- 自定义SQL关联:通过
JOIN两个postmeta表,确保date_from和date_to属于同一个Repeater子项(用REPLACE匹配对应字段)。 - 正确的重叠条件:
mf.meta_value <= $user_date_to(子项起始不晚于用户结束)且mt.meta_value >= $user_date_from(子项结束不早于用户起始),覆盖所有重叠场景。 - 空值处理:避免用户未输入日期时返回所有文章。
- 日期格式转换:确保用户输入的日期转换为MySQL支持的
YYYY-MM-DD格式,避免查询错误。
内容的提问来源于stack exchange,提问作者Павел
相关产品推荐
相关产品推荐

