Вопрос или проблема
Следующие аргументы используются для 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
, запрос не обнаруживает конфликт, так как поиск проводится по отдельным мета-ключам.
Решение
Чтобы идентифицировать пересечения временных интервалов, нам нужно подойти к задаче, учитывая два условия:
- Новый начальный интервал должен быть меньше предшествующего конечного интервала.
- Новый конечный интервал должен быть больше предшествующего начального интервала.
Таким образом, правильный подход будет следующим:
$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();
Объяснение изменений
-
Логика OR: Мы используем условие, чтобы запрос был успешным, если либо
start_date
больше или равенend_date
нового резервирования, либоend_date
меньше или равенstart_date
нового резервирования. Это позволяет находить все возможные записи, которые могут пересекаться с новым резервированием. -
Фильтрация по статусу: Мы добавили фильтрацию по статусу публикации, чтобы включить только те записи, которые доступны для пользовательской интерактивной части.
-
Сброс данных: Использование
wp_reset_postdata()
после цикла позволяет вернуть глобальный объект поста к первоначальному состоянию.
Заключение
Это решение обеспечит корректный поиск возможных конфликтов при создании новых резервирований. Используя данный подход, вы не только улучшите функциональность вашего сайта, но и повысите его пользовательскую привлекательность.
Следите за тем, чтобы при тестировании запросов корректно использовать формат даты и времени, как требуемо вашими мета-данными. Надеюсь, предложенное решение станет для вас полезным.