Вопрос или проблема
Мой цикл отображает избранные посты, а затем посты в обратном хронологическом порядке.
Однако, когда я использую <?php echo get_previous_post(); ?>
, он берёт посты в обратном хронологическом порядке.
Как мне добавить фильтр к функции предыдущего поста, аналогичный этому, но вместо этого фильтруя по массиву, как: 'orderby' => array( 'meta_value' => 'DESC', 'date' => 'DESC')
?
Код:
ОБНОВЛЕНИЕ: Убрал лишние элементы в цикле index.php после помощи от @sMyles и @JackJohansson
Цикл index.php:
$args = array(
'posts_per_page' => - 1,
'meta_key' => 'meta-checkbox',
'orderby' => array( 'meta_value' => 'DESC', 'date' => 'DESC')
);
$posts = new WP_Query( $args );
if($posts->have_posts() ){
while( $posts->have_posts() ){
$posts->the_post();
// Устанавливаем шаблон контента по умолчанию
$template="content";
// Меняем шаблон на избранный, когда мета `is_featured` имеет значение
if(get_post_meta(get_the_ID(), 'meta-checkbox', 'yes')){
$template="featured";
}
// Загружаем часть шаблона
get_template_part( $template, get_post_format() );
}
}
ОБНОВЛЕНИЕ: Как было предложено, я добавил, где использую функцию предыдущего поста
Функция Предыдущего Поста
<div id="next-post">
<?php $prev_post = get_previous_post();
if(!empty($prev_post)) {
echo '<a class="next-story" href="' . get_permalink($prev_post->ID) . '">Следующая История</a>';
echo '<a class="next-story-title" href="' . get_permalink($prev_post->ID) . '" title="' . $prev_post->post_title . '">' . $prev_post->post_title . '</a>';
} ?>
</div>
Функция Для Избранных Постов:
function sm_custom_meta() {
add_meta_box( 'sm_meta', __( 'Избранные Посты', 'sm-textdomain' ), 'sm_meta_callback', 'post' );
}
function sm_meta_callback( $post ) {
$featured = get_post_meta( $post->ID );
?>
<p>
<div class="sm-row-content">
<label for="meta-checkbox">
<input type="checkbox" name="meta-checkbox" id="meta-checkbox" value="yes" <?php if ( isset ( $featured['meta-checkbox'] ) ) checked( $featured['meta-checkbox'][0], 'yes' ); ?> />
<?php _e( 'Избранный этот пост', 'sm-textdomain' )?>
</label>
</div>
</p>
<?php
}
add_action( 'add_meta_boxes', 'sm_custom_meta' );
function sm_meta_save( $post_id ) {
// Проверяет статус сохранения
$is_autosave = wp_is_post_autosave( $post_id );
$is_revision = wp_is_post_revision( $post_id );
$is_valid_nonce = ( isset( $_POST[ 'sm_nonce' ] ) && wp_verify_nonce( $_POST[ 'sm_nonce' ], basename( __FILE__ ) ) ) ? 'true' : 'false';
// Выход из скрипта в зависимости от статуса сохранения
if ( $is_autosave || $is_revision || !$is_valid_nonce ) {
return;
}
// Проверяет ввод и сохраняет
if( isset( $_POST[ 'meta-checkbox' ] ) ) {
update_post_meta( $post_id, 'meta-checkbox', 'yes' );
} else {
update_post_meta( $post_id, 'meta-checkbox', '' );
}
}
add_action( 'save_post', 'sm_meta_save' );
Вам следует просто сделать новый полный запрос для всех постов (не только избранных) и установить orderby
на meta_value
, а затем просто проверить в цикле, имеет ли этот пост мета значение yes
, и вывести избранный шаблон, иначе вывести стандартный.
https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters
ОБНОВЛЕНИЕ:
Может что-то вроде этого:
$args = array(
'posts_per_page' => - 1,
'meta_key' => 'meta-checkbox',
'orderby' => array( 'meta_value' => 'DESC', 'date' => 'DESC')
);
$posts = new WP_Query( $args );
if($posts->have_posts() ){
while( $posts->have_posts() ){
$posts->the_post();
// Устанавливаем шаблон контента по умолчанию
$template="content";
// Меняем шаблон на избранный, когда мета `is_featured` имеет значение
if(get_post_meta(get_the_ID(), 'meta-checkbox', true)){
$template="featured";
}
// Загружаем часть шаблона
get_template_part( $template, get_post_format() );
}
}
Вы заметите, что я изменил мета ключ на is_featured
.. это хорошая практика использовать подчеркивания вместо дефисов.
Чтобы получить значение мета для поста, просто используйте объект $post
, который имеет магический метод PHP __get
, который вернёт мета поста, если она существует.
http://php.net/manual/en/language.oop5.overloading.php#object.get
Добавьте это в файл functions.php
вашей дочерней темы, чтобы изменить основной запрос цикла постов:
add_action( 'pre_get_posts', 'smyles_main_query_custom_orderby' );
/**
* Измените основной запрос постов, сортируя по мета ключу и дате
*
* @param \WP_Query $query
*/
function smyles_main_query_custom_orderby( $query ) {
// Подтверждает, что запрос является основным архивом блога
if ( $query->is_home() && $query->is_main_query() ) {
$query->set( 'meta_key', 'meta-checkbox' );
$query->set( 'orderby', array( 'meta_value' => 'DESC', 'date' => 'DESC' ) );
}
}
https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts
https://make.wordpress.org/core/2014/08/29/a-more-powerful-order-by-in-wordpress-4-0/
Ваш цикл в файле index.php
может выглядеть так:
if ( have_posts() ) {
while( have_posts() ) {
the_post();
$template = get_post_meta( get_the_ID(), 'meta-checkbox', true ) ? 'featured' : 'content';
// Это могло бы быть просто код ниже, если бы вы использовали подчеркивания, как я упомянул ранее
// $template = $post->meta_checkbox ? 'featured' : 'content';
// Загружаем часть шаблона
get_template_part( $template, get_post_format() );
}
}
Ответ или решение
Чтобы отфильтровать функцию get_previous_post
, используя значения метаданных в порядке убывания, а также дату публикации в убывающем порядке, необходимо внести изменения в стандартное поведение этой функции. Давайте подробно разберем, как это сделать.
Контекст задачи
Ваша функция get_previous_post()
по умолчанию возвращает предыдущий пост в обратном хронологическом порядке. Это не всегда соответствует вашим требованиям, особенно если вы хотите учитывать мета-значения и дату публикации. Вам необходимо модифицировать логику извлечения постов, чтобы учитывать указанные вами параметры: meta_value
и date
.
Решение
- Создание собственного запроса для предыдущего поста:
Чтобы получать предыдущий пост с определенными параметрами сортировки, нам придется создать новый запрос. Для этого используйте класс WP_Query
. Мы можем использовать параметр meta_key
для фильтрации постов по метадатам и задать порядок сортировки в аргументах.
- Код для получения предыдущего поста:
Ниже представлен код, который вы можете использовать для получения предыдущего поста с учетом указанных критериев сортировки:
function get_custom_previous_post() {
// Получаем текущий пост
global $post;
// Устанавливаем параметры запроса
$args = array(
'posts_per_page' => 1,
'meta_key' => 'meta-checkbox', // Замена на ключ метаданных
'meta_value' => 'yes', // Убедитесь, что у вас есть такая проверка
'orderby' => array('meta_value' => 'DESC', 'date' => 'DESC'),
'order' => 'DESC',
'post_type' => 'post', // Убедитесь, что это нужный тип поста
'post_status' => 'publish',
'date_query' => array(
array(
'before' => $post->post_date // Получаем пост, который был до текущего
)
)
);
// Новый запрос
$query = new WP_Query($args);
// Если пост найден, возвращаем его
if($query->have_posts()) {
$query->the_post(); // Устанавливаем пост из запроса
return $post; // Возвращаем текущий объект поста
}
// Сбрасываем данные запроса
wp_reset_postdata();
return null; // Если пост не найден
}
// Использование функции
$prev_post = get_custom_previous_post();
if($prev_post) {
echo '<a class="prev-story" href="' . get_permalink($prev_post->ID) . '">Предыдущая история</a>';
echo '<a class="prev-story-title" href="' . get_permalink($prev_post->ID) . '" title="' . $prev_post->post_title . '">' . $prev_post->post_title . '</a>';
}
Объяснение кода
-
Создание аргументов запроса: Мы настраиваем массив
$args
, который включает параметры сортировки по метадатеmeta-checkbox
и дате публикации. -
Запрос: Используем
WP_Query
для выполнения запроса и получения поста, соответствующего заданным критериям. -
Логика: После выполнения запроса мы проверяем, найден ли предыдущий пост, и выводим его заголовок и ссылку.
Заключение
Используя предложенное решение, вы сможете фильтровать предыдущие посты по метадатам и дате публикации, получая желаемый результат. Обязательно протестируйте изменения на локальной среде перед развертыванием на живом сайте. Это обеспечит стабильность и правильное поведение вашего сайта.