Как создать лучший WP_Query для поиска даты и времени, которые находятся между двумя мета-значениями?

Вопрос или проблема

Следующие аргументы используются для WP_Query, чтобы проверить, можно ли создать резервирование для игры.
Мета-поля ввода для поста создаются с помощью ACF DateTime Picker и устанавливаются в Y-m-d H:i:s

$start_date="2019-08-31 12:15:00";
$end_date="2019-08-31 12:20:00";

$args = array(
    'post_type' => 'rezervacija',
    'posts_per_page' => -1,
    'meta_query' => array(
        'relation' => 'AND',
        array(
            'relation' => 'OR',
            array(
                'key' => 'start_date',
                'value' => array($start_date, $end_date),
                'compare' => 'BETWEEN',
                'type' => 'DATETIME'
                ),
            array(
                'key' => 'end_date',
                'value' => array($start_date, $end_date),
                'compare' => 'BETWEEN',
                'type' => 'DATETIME'
                )
            ),
        array(
            'key' => 'location', // Также ищите конкретную площадку, это не важно для данного вопроса
            'value' => 3,
            'compare' => '='
            )
        )
    );

$query = new WP_Query($args);

Этот код в общем работает, но не полностью так, как ожидалось.
Если уже существует резервирование с начальной датой, установленной на 12:00 (2019-08-31 12:00:00), и конечным временем 14:00 (2019-08-31 14:00:00), а затем новый пользователь выбирает время 12:15 и конечное время 13:30, в этом случае, поскольку запрос ищет эти значения отдельно, он не найдет ничего, хотя должен. Таким образом, в общем, этот запрос не сможет правильно найти данные, когда время находится где-то внутри предыдущих временных резервирований.

Как я могу изменить этот запрос, чтобы искать посты, чьи $start_date и $end_date находятся где-то между значениями start_date и end_date?

Вам может потребоваться сделать это для запроса между двумя датами:

$query = new WP_Query(array(
                        'post_type' => 'rezervacija',
                        'posts_per_page' => -1,
                        'post_status' => 'publish',
                        'meta_query' => array(
                                'relation' => 'AND',
                                array(
                                    'key'     => 'start_date',
                                    'value'   => current_time('Ymd'), //измените это в соответствии с вашими нуждами.
                                    'compare' => '>=',
                                ),
                                array(
                                    'key'     => 'end_date',
                                    'value'   => current_time('Ymd'), //измените это в соответствии с вашими нуждами.
                                    'compare' => '<=',
                                ),

                            ),
                    ));

    if ($query->have_posts()) : 
        while($query->have_posts()) : 
            $query->the_post();
            the_permalink(); 
            the_title();
        endwhile;  
    endif;

Ответ или решение

Для решения проблемы с использованием WP_Query, чтобы корректно искать резервируемые временные интервалы между двумя мета-значениями, нужно изменить подход к построению meta_query. Разберем более детально, как вам следует модифицировать запрос.

Проблема

Исходный код выполняет успешный поиск по start_date и end_date, но не учитывает перекрытия временных интервалов. Например, если уже существует запись с начальной датой 2019-08-31 12:00:00 и конечной датой 2019-08-31 14:00:00, а пользователь пытается сделать резервирование с 2019-08-31 12:15:00 по 2019-08-31 13:30:00, запрос не обнаруживает конфликт, так как поиск проводится по отдельным мета-ключам.

Решение

Чтобы идентифицировать пересечения временных интервалов, нам нужно подойти к задаче, учитывая два условия:

  1. Новый начальный интервал должен быть меньше предшествующего конечного интервала.
  2. Новый конечный интервал должен быть больше предшествующего начального интервала.

Таким образом, правильный подход будет следующим:

$start_date = "2019-08-31 12:15:00";
$end_date = "2019-08-31 13:30:00";

$args = array(
    'post_type'      => 'rezervacija',
    'posts_per_page' => -1,
    'post_status'    => 'publish',
    'meta_query'     => array(
        'relation' => 'OR',
        array(
            'key' => 'start_date',
            'value' => $end_date,
            'compare' => '>=',
            'type' => 'DATETIME'
        ),
        array(
            'key' => 'end_date',
            'value' => $start_date,
            'compare' => '<=',
            'type' => 'DATETIME'
        ),
    ),
);

$query = new WP_Query($args);

if ($query->have_posts()) : 
    while ($query->have_posts()) : $query->the_post();
        the_permalink(); 
        the_title();
    endwhile;  
else:
    echo 'Нет доступных резервирований для выбранных дат.';
endif;
wp_reset_postdata();

Объяснение изменений

  1. Логика OR: Мы используем условие, чтобы запрос был успешным, если либо start_date больше или равен end_date нового резервирования, либо end_date меньше или равен start_date нового резервирования. Это позволяет находить все возможные записи, которые могут пересекаться с новым резервированием.

  2. Фильтрация по статусу: Мы добавили фильтрацию по статусу публикации, чтобы включить только те записи, которые доступны для пользовательской интерактивной части.

  3. Сброс данных: Использование wp_reset_postdata() после цикла позволяет вернуть глобальный объект поста к первоначальному состоянию.

Заключение

Это решение обеспечит корректный поиск возможных конфликтов при создании новых резервирований. Используя данный подход, вы не только улучшите функциональность вашего сайта, но и повысите его пользовательскую привлекательность.

Следите за тем, чтобы при тестировании запросов корректно использовать формат даты и времени, как требуемо вашими мета-данными. Надеюсь, предложенное решение станет для вас полезным.

Оцените материал
Добавить комментарий

Капча загружается...