You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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',
                ],
            ],

错误原因分析

  1. 字段匹配逻辑错误:原代码的meta_query使用AND关系,但未确保date_ranges_$_date_from和date_ranges_$_date_to属于Repeater的同一个子项。数据库会将任意子项的date_from和另一个子项的date_to进行匹配,导致错误触发条件。
  2. 日期重叠逻辑错误:原代码的条件只判断了“文章的所有子项起始日期≤用户结束日期,且所有子项结束日期≥用户起始日期”,这不符合“任意子项与用户范围重叠”的需求。

正确解决方案

要实现“任意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');

代码说明

  1. 自定义SQL关联:通过JOIN两个postmeta表,确保date_from和date_to属于同一个Repeater子项(用REPLACE匹配对应字段)。
  2. 正确的重叠条件:mf.meta_value <= $user_date_to(子项起始不晚于用户结束)且mt.meta_value >= $user_date_from(子项结束不早于用户起始),覆盖所有重叠场景。
  3. 空值处理:避免用户未输入日期时返回所有文章。
  4. 日期格式转换:确保用户输入的日期转换为MySQL支持的YYYY-MM-DD格式,避免查询错误。

内容的提问来源于stack exchange,提问作者Павел

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 20:05:56