Вопрос или проблема
Я пытаюсь настроить “резервный” запрос для wp_query. Я хочу получить первый пост, которому один год, но если такого не существует, получить пост, которому один год и один день. А затем сохранить этот HTML в Advanced Custom Field on_this_day_1_year_ago. Первый код работает для одного поста, второй код с резервным вариантом ниже не работает и не дает никаких ошибок PHP. (Я знаю, что мое использование strtotime немного неаккуратное, и вся эта функция вероятно ресурсоемкая для базы данных).
Это то, с чего я начал; простой wp_query для поста годичной давности, и это работает.
$one_year_ago = date('Y-m-d', strtotime('-1 year'));
$args = array(
'post_type' => 'post',
'posts_per_page' => 1,
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'date_query' => array(
array(
'year' => date('Y', strtotime($one_year_ago)),
'month' => date('m', strtotime($one_year_ago)),
'day' => date('d', strtotime($one_year_ago)),
),
),
);
$query = new WP_Query( $args );
ob_start();
while( $query->have_posts() ) {
$query->the_post();
echo '<a href="' . get_permalink() '">';
the_title();
echo '</a>';
}
endwhile;
wp_reset_postdata();
$this_day_one_year_ago = ob_get_clean();
// Сохранение в поле ACF
update_field('on_this_day_1_year_ago', $this_day_one_year_ago, 'option');
Это резервный вариант для поста годичной давности и одного дня, который не работает. Какие-то идеи? Думаю, проблема в output_posts()
date_default_timezone_set('America/Chicago');
$one_year_ago = date('Y-m-d', strtotime('-1 year'));
$one_year_ago_plus_day = date('Y-m-d', strtotime('-367 days'));
function output_posts( $query ){
// получение вывода для сохранения в Advanced Custom Field
ob_start();
while( $query->have_posts() ) {
$query->the_post();
echo '<a href="' . get_permalink() '">';
the_title();
echo '</a>';
}
wp_reset_postdata();
$this_day_one_year_ago = ob_get_clean();
// сохранение в настраиваемое поле
update_field('on_this_day_1_year_ago', $this_day_one_year_ago, 'option');
}
// аргументы для поста годичной давности
$args = array(
'post_type' => 'post',
'posts_per_page' => 1,
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'date_query' => array(
array(
'year' => date('Y', strtotime($one_year_ago)),
'month' => date('m', strtotime($one_year_ago)),
'day' => date('d', strtotime($one_year_ago)),
),
),
);
$query = new WP_Query( $args );
// Если в запросе есть посты
if( $query->have_posts() ) {
output_posts( $query );
// или резервный вариант - 367 дней
} else {
// аргументы для поста годичной давности и одного дня
$args = array(
'post_type' => 'post',
'posts_per_page' => 1,
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'date_query' => array(
array(
'year' => date('Y', strtotime($one_year_ago_plus_day)),
'month' => date('m', strtotime($one_year_ago_plus_day)),
'day' => date('d', strtotime($one_year_ago_plus_day)),
),
),
);
$fallback = new WP_Query( $args );
if ( $fallback->have_posts() ){
output_posts( $fallback );
}
}
Ответ или решение
Для решения задачи по созданию "аварийного" механизма для получения результатов WP_Query необходимо учитывать специфические детали работы с WP_Query и управлением датами в PHP. Давайте разберем этот процесс, чтобы обеспечить корректную работу вашего кода.
Теория
WP_Query — это класс в WordPress, который позволяет выполнять запросы к базе данных для извлечения записей, соответствующих определенным критериям. В вашем случае задача заключается в получении записи, опубликованной ровно год назад. Если таких записей нет, необходимо получить первую запись, опубликованную на день раньше (1 год и 1 день назад).
Пример
Далее я предоставлю исправленный и оптимизированный пример кода для вашей задачи. Рассмотрим типичные ошибки и ко
рректировки при работе с WP_Query:
date_default_timezone_set('America/Chicago');
// Определение дат для запросов
$one_year_ago = date('Y-m-d', strtotime('-1 year'));
$one_year_ago_plus_day = date('Y-m-d', strtotime('-367 days'));
// Функция для обработки и сохранения результатов запроса
function output_posts($query) {
ob_start();
while ($query->have_posts()) {
$query->the_post();
echo '<a href="' . get_permalink() . '">';
the_title();
echo '</a>';
}
wp_reset_postdata();
$this_day_one_year_ago = ob_get_clean();
// Сохранение в поле ACF
update_field('on_this_day_1_year_ago', $this_day_one_year_ago, 'option');
}
// Параметры запроса для поиска записи год назад
$args = array(
'post_type' => 'post',
'posts_per_page' => 1,
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'date_query' => array(
array(
'after' => date('Y-m-d', strtotime('-1 year -1 day')),
'before' => date('Y-m-d', strtotime('-1 year +1 day')),
'inclusive' => true,
),
),
);
$query = new WP_Query($args);
if ($query->have_posts()) {
output_posts($query);
} else {
// Параметры запроса для поиска записи год и один день назад
$args['date_query'] = array(
array(
'year' => date('Y', strtotime($one_year_ago_plus_day)),
'month' => date('m', strtotime($one_year_ago_plus_day)),
'day' => date('d', strtotime($one_year_ago_plus_day)),
),
);
$fallback = new WP_Query($args);
if ($fallback->have_posts()) {
output_posts($fallback);
}
}
Применение
В данном решении мы используем:
-
ob_start()
иob_get_clean()
: Эти функции PHP полезны для временного хранения вывода функций, таких какthe_title()
иget_permalink()
, перед их сохранением в пользовательское поле ACF. -
Массив
date_query
: Чтобы избежать повторяющегося кода и сделать запросы более гибкими и корректными по времени, мы используем диапазон дат вместо строгого соответствия. -
Функция
output_posts($query)
: Отдельная функция для обработки вывода позволяет избежать дублирования кода при обработке основного запроса и "аварийного" механизма.
Этот подход улучшает структуру и производительность кода, обеспечивая выполнение вашей задачи более эффективно и надежно.