Июл
20
0

Закрепленные записи sticky post в категориях / тегах блога без плагина

sticky post в категорияхДанная фишка Вордпресс “закрепляет” любой пост самым первым на главной странице независимо от его даты написания (напоминаю, в блоге записи выводятся по новизне). Это позволяет сразу показывать посетителям наиболее актуальный или важный контент. Если вы новичок, смотрите публикацию про создание и оформление sticky post, а дальше уже можете ознакомиться с сегодняшним хаком. Он автоматически фиксирует “липкие” посты сверху на страницах архивов категорий и тегов. В статье постараюсь максимально доходчиво объяснить всю логику метода.

Обновление 05.12.2019: Буквально недавно я рассматривал плагины sticky post в WordPress среди которых найдете альтернативное решение этой задачи и некоторые другие полезные модули по теме.

Включить данную опцию для поста можете как при его редактировании, так в общем разделе со списком всех публикаций. В первом случае это выглядит так (слева Gutenberg, справа старый редактор).

Закрепленные записи sticky post

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

Исходный код нашел здесь выглядит он следующим образом (это полностью рабочий экземпляр, но тут есть нюансы, которые я слегка переделал… тем не менее, логику рассмотрим на этом примере):

function get_term_sticky_posts()
{
    // Проверка находимся ли мы на странице архива категорий / category page... если нет - возвращает false
    if ( !is_category() )
        return false;
 
    // Во-вторых, смотрим если вообще закрепленные посты, в противном случае - опять возвращаем false
    $stickies = get_option( 'sticky_posts' );
 
    if ( !$stickies )
        return false;
 
    // Ок, sticky-заметки имеются, и мы находимся в архиве рубрики, тогда считываем ID текущего category-объекта
    $current_object = get_queried_object_id();
 
    // Создание запроса на получение прилепленных постов в разделе, получаем ID постов
    $args = [
        'nopaging' => true,
        'post__in' => $stickies,
        'cat' => $current_object,
        'ignore_sticky_posts' => 1,
        'fields' => 'ids'
    ];
    $q = get_posts( $args );
 
    return $q;
}
 
add_action( 'pre_get_posts', function ( $q )
{
    if (    !is_admin() // ВАЖНО, чтобы выполнялось только во фронт-энде
         && $q->is_main_query() // ВАЖНО, работаем только с main query
         && $q->is_category() // Срабатывает только для архивов категорий
    ) {
        // Проверка определена ли наша функция липких постов выше дабы не было ошибок
        if ( function_exists( 'get_term_sticky_posts' ) ) {
            // Смотрим есть ли вообще закрепленные записи
            $stickies = get_term_sticky_posts();
 
            if ( $stickies ) {
                // Далее удаляем найденные прилипленные публикации дабы в итоговом результате не было дублей
                $q->set( 'post__not_in', $stickies );
 
                // Выводим sticky-посты только на первой странице архива, если надо на всех, аккуратно убираете данное условие
                if ( !$q->is_paged() ) {
 
                    // Добавляем липкие заметки перед остальными с помощью фильтра the_posts
                    add_filter( 'the_posts', function ( $posts ) use ( $stickies )
                    {   
                        $term_stickies = get_posts( ['post__in' => $stickies, 'nopaging' => true] );
 
                        $posts = array_merge( $term_stickies, $posts );
 
                        return $posts;
                    }, 10, 1 );
                }
            }
        }
    }
});

Итак, тут имеются 2 блока:

  1. Новая функция get_term_sticky_posts, что считывает все прикрепленные посты из текущей активной категории. Пошаговый алгоритм вы можете прочитать в комментариях кода, которые я перевел с английского. Здесь также не обошлось без функции get_queried_object, рассмотренной в прошлом посте.
  2. Дальше с помощью хука “вклиниваетесь” в событие pre_get_posts до выполнения WP_Query и запроса в БД, дабы, во-первых, считать список прикрепленных постов и, во-вторых, разместить его перед всеми остальными записями. Опять же смотрите комменты в примере выше.

Несколько дополнений от автора:

  • Данный сниппет добавляете в файл functions.php и все, никаких дополнительных правок шаблонов категорий/архивов не нужно. Это плюс!
  • Код выше работает только для категорий (category), но может быть легко модифицирован и под другие таксономии. Еще один плюс.
  • Для работы надо как минимум PHP 5.4+!

НО есть одна неприятная ошибка! 

В том же треде на stackexchange имеется замечание, что хак не справляется с ситуацией, когда в URL-адресе пользователь допустит ошибку в названии раздела, например – site.com/categggory/ — вместо того чтобы выдать страницу 404 ошибки система посчитает это названием реальной таксономии, т.к. значение будет сохранено в переменную $q.

Закрепленные записи sticky post

К сожалению, предложенный вариант с использованием is_tax у меня не прокатил, возможно, потому что данная функции срабатывает для новых пользовательских таксономий и игнорирует теги/разделы. Вместо этого я пробовал использовать term_exists() – вроде как, сработало.

Мой вариант

Эта версия сниппета закрепляет записи sticky post не только в рубриках, но и для тегов. Кроме того, ошибка с неправильным вводом таксономии все же ведет на 404 ошибку, как и должно быть.

function get_term_sticky_posts()
{
    if (( !is_category() ) && ( !is_tag() ))
        return false;
 
    $stickies = get_option( 'sticky_posts' );
 
    if ( !$stickies )
        return false;
 
    $current_object = get_queried_object_id();
 
    if ( is_category() ) {
    $args = [
        'nopaging' => true,
        'post__in' => $stickies,
        'cat' => $current_object,
        'ignore_sticky_posts' => 1,
        'fields' => 'ids'
    ];
 
    } elseif ( is_tag() ) {
    $args = [
        'nopaging' => true,
        'post__in' => $stickies,
        'tag_id' => $current_object,
        'ignore_sticky_posts' => 1,
        'fields' => 'ids'
    ];
    }
 
    $q = get_posts( $args );
 
    return $q;
}
 
add_action( 'pre_get_posts', function ( $q )
{
 
    if (    !is_admin()
        && $q->is_main_query() 
        && ( ($q->is_category()) || ($q->is_tag()) ) 
        && ( (term_exists(get_query_var('category_name'))) || (term_exists(get_query_var('tag'))) )
    ) {
 
        if ( function_exists( 'get_term_sticky_posts' ) ) {
 
            $stickies = get_term_sticky_posts();
 
            if ( $stickies ) {
 
                $q->set( 'post__not_in', $stickies );
 
 
                if ( !$q->is_paged() ) {
 
 
                    add_filter( 'the_posts', function ( $posts ) use ( $stickies )
                    {   
                        $term_stickies = get_posts( ['post__in' => $stickies, 'nopaging' => true] );
 
                        $posts = array_merge( $term_stickies, $posts );
 
                        return $posts;
                    }, 10, 1 );
                }
            }
        }
    }
});

По коддингу тут лишь несколько логических изменений:

  • Во-первых, для хука pre_get_posts я добавил обработку тегов и проверку на существование названия введенной таксономии (term_exists).
  • Во-вторых, в функцию get_term_sticky_posts вставил обработку меток (проверки + считывание соответствующих закрепленных постов).

Решение я тестил на последних версиях WordPress 5.2.x, при этом версия PHP 5.6+. Пока полет нормальный. Из альтернатив можно глянуть модуль Category Sticky Post, но он несколько лет не обновлялся. Если есть что дополнить, пишите.

рейтинг Оцените статью:
Ужасная статьяНичего интересногоТак себеНормальноХорошоКлассный постВ закладки!
(голосов - 14, средний балл: 4,14 из 7)
Загрузка...

категория Категории: Хаки и секреты;
теги Теги: , , , , , .
Оставить комментарий


Блог Wordpress Inside поможет вам научиться работать в вордпресс, закрепить и расширить имеющиеся знания. Плагины и шаблоны, разные хаки и функции wp, оптимизация и безопасность системы – все это и намного больше вы сможете найти на страницах нашего проекта!

Если хотите быстро и оперативно получать последние новости и статьи, то рекомендуем подписаться на обновления блога:

Поиск:
Последние посты
Лучшее в категории

Облако тегов
Скажи свое мнение!

В чем основные плюсы Wordpress?

Посмотреть результаты

Загрузка ... Загрузка ...
Друзья проекта
Последние новости