Плагин WordPress. Исключаем ненужные категории.

Владимир | | HTML, PHP, Web разработка, WordPress.

wordpress plugin exclude categories

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

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

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

Для чего это может понадобиться.

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

2) Вы занимаетесь размещением платных статей. Тут вообще всё просто. Постоянные читатели вряд ли оценят seo'шную статью о преимуществах очередного интернет магазина 🙂 В тоже время, монетизировать блог как-то нужно.

Возвращаемся к реализации.

Сразу даю ссылку на архив

Source

UPD. Плагин обновлен для использования с WP 3.1.

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

Установка и подключение точно такие же, как и у большинства плагинов. Архив нужно распаковать в папку wp-content\plugins и активировать в панели у правления. После этого в разделе Settings появится страница с настройками плагина.

wp plugin exclude categories admin

Отмечаете нужные категории, и решаете где их не нужно показывать.

Теперь разберем реализацию плагина.

Начало стандартное.

/*
Plugin Name: Exclude Category Plugin
Plugin URI: http://www.simplecoding.org/plagin-wordpress-isklyuchaem-nenuzhnye-kategorii.html
Description: Позволяет убрать посты указанных категорий с главной страницы и из RSS ленты.
Version: 1.0
Author: Statsenko Vladimir
Author URI: http://www.simplecoding.org
*/

Этот комментарий содержит данные, которые отображаются на панели управления плагинами.

Создание страницы в панели управления.

Нам нужно выполнить два действия: создать новый пункт в меню Settings и создать форму с настройками плагина.

Начнём с создания формы.

  1. <?php
  2. function ec_settings_page() {
  3.   //получаем список категорий
  4.   $categories = get_categories(array('hide_empty' => false));
  5. ?>
  6. <div class="wrap">
  7.   <h2>Exclude Category Plugin Settings</h2>
  8.   <form method="post" action="options.php">
  9.     <?php
  10.       //Необходимо для автоматической обработки формы
  11.       settings_fields( 'ec-settings-group' );
  12.     ?>
  13.     <table class="form-table">
  14.       <tbody>
  15.         <tr valign="top">
  16.           <th scope="row">Выберите категории, которые нужно исключить</th>
  17.           <td>
  18.             <fieldset>
  19.               <legend class="screen-reader-text"><span>Выберите категории, которые нужно исключить</span></legend>
  20.             <?php
  21.               //читаем значение текущее опции
  22.               $curCL = get_option('cats_list');
  23.               foreach ($categories as $category) {
  24.                 $checked = '';
  25.                 if (is_array($curCL) && in_array($category->cat_ID, $curCL)) {
  26.                   $checked = 'checked="checked"';
  27.                 }
  28.                 echo '<label><input '.$checked.' type="checkbox" name="cats_list[]" value="'.$category->cat_ID.'" /> '.$category->name.'</label><br />';
  29.               }
  30.             ?>
  31.             </fieldset>
  32.           </td>
  33.         </tr>
  34.         <tr valign="top">
  35.           <th scope="row">Не выводить выбранные категории</th>
  36.           <td>
  37.             <fieldset>
  38.               <legend class="screen-reader-text"><span>Не выводить выбранные категории</span></legend>
  39.               <?php
  40.                 $curCH = get_option('cats_home');
  41.                 $cH = $cF = '';
  42.                 if (is_array($curCH)) {
  43.                   $cH = in_array('home', $curCH) ? 'checked="checked"' : '';
  44.                   $cF = in_array('feed', $curCH) ? 'checked="checked"' : '';
  45.                 }
  46.               ?>
  47.               <label><input type="checkbox" <?php echo $cH; ?> name="cats_home[]" value="home" /> на главной</label><br />
  48.               <label><input type="checkbox" <?php echo $cF; ?> name="cats_home[]" value="feed" /> в RSS ленте</label>
  49.             </fieldset>
  50.           </td>
  51.         </tr>
  52.       </tbody>
  53.     </table>
  54.     <p class="submit"><input type="submit" class="button-primary" value="Сохранить" /></p>
  55.   </form>
  56. </div>
  57.  
  58. <?php
  59. }
  60. ?>

* This source code was highlighted with Source Code Highlighter.

Получилась она довольно объёмной, но в основном из-за разметки. Кода совсем немного.

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

Перед отображением формы мы получаем список всех постов с помощью функции get_categories. Внутри формы создаём группу чекбоксов для них. Атрибут name у этой группы имеет значение cats_list[].

Вторая группа чекбоксов позволяет указать, откуда нужно исключить записи. У неё атрибут name равен cats_home[].

Теперь обратите внимание на функцию settings_fields('ec-settings-group'), которую мы вызываем сразу после открытия формы. Она создаёт несколько скрытых полей, с помощью которых автоматически выполняется сохранение данных, введённых в форму.

Но для того, чтобы эта возможность заработала необходимо зарегистрировать оба наших набора чекбоксов.

function register_ec_settings() {
	register_setting( 'ec-settings-group', 'cats_list' );
	register_setting( 'ec-settings-group', 'cats_home' );
}

В первом параметре функции register_setting передаём имя группы (оно должно совпадать с параметром, переданным settings_fields). Во втором параметре указываем атрибут name группы чекбоксов.

Теперь, при сохранении формы данные автоматически будут записаны в таблицу wp_options (при этом выполняется их сериализация).

Получить сохранённые данные можно с помощью функции settings_fields. Что мы и делаем перед формированием списка чекбоксов в форме. Проверку, есть ли текущая категория среди выбранных ранее, выполняем с помощью функции is_array.

Добавляем новый пункт в меню Settings

  1. //создаём подменю Settings->Exclude Category Plugin и соответствующую форму
  2.  
  3. //регистрируем функцию создания меню
  4. add_action('admin_menu', 'ec_create_menu');
  5.  
  6. //функция создания меню
  7. function ec_create_menu() {
  8.   add_submenu_page('options-general.php'
  9.            ,'Exclude Category Plugin Settings'
  10.            , 'Exclude Category'
  11.            , 'edit_plugins'
  12.            , __FILE__
  13.            , 'ec_settings_page');
  14.   
  15.   //Регистрируем функцию register_ec_settings. Она нужна для автоматической
  16.   //обработки формы с настройками
  17.   add_action( 'admin_init', 'register_ec_settings' );
  18. }

* This source code was highlighted with Source Code Highlighter.

Сам пункт создаётся с помощью функции add_submenu_page, в параметрах которой необходимо указать различные настройки. Перечислять их все я не буду, лучше дам ссылку на статью с подробным описанием. Но, обратите внимание, что в последнем параметре указано имя функции, создающей форму.

Для того, чтобы WP создал меню, нужно добавить действие (add_action). В её первом параметре мы указываем название действия в котором мы хотим выполнить наш код (в данном случае это admin_menu), во втором параметре – имя функции, которую нужно выполнить, именно в ней должен быть вызов add_submenu_page. Кроме того, в этой функции мы добавляем еще одно действие — admin_init, и в нём регистрируем обработчик register_ec_settings.

На данном этапе у нас есть рабочая форма в админке с двумя наборами чекбоксов. Все отмеченные чекбоксы сохраняются в базе данных (таблица wp_options) и доступ к ним можно получить с помощью get_option('cats_home') и get_option('cats_list').

Рассмотрим принцип удаления постов.

Список постов движок WP получает из базы данных с помощью обычного запроса. Т.е. нам нужно добавить к этому запросу условия, которые исключат ненужные нам категории.

Для этого, нам нужно создать фильтр, который выполнит наш код до отправки запроса движком. Делается это следующим образом.

add_filter('pre_get_posts','ec_exclude');

Событие pre_get_posts возникает как раз перед отправкой запроса, а ec_exclude – название нашей функции, причем в первом её параметре WP передаст объект с запросом. Рассмотрим её подробнее.

  1. function ec_exclude($query) {
  2.   //читаем массивы с опциями
  3.   if (is_array($target = get_option('cats_home'))) {
  4.     if (is_array($categories = get_option('cats_list'))) {
  5.       //добавляем к id категорий знак "-"
  6.       foreach ($categories as $i => $category) {
  7.         $categories[$i] = '-'.$categories[$i];
  8.       }
  9.       //формируем строку с перечнем категорий
  10.       $cat_string = implode(',', $categories);
  11.       //удаляем посты указанных категорий из RSS ленты
  12.       if (in_array('feed', $target) && $query->is_feed) {
  13.         $query->set('cat',$cat_string);
  14.       }
  15.       //удаляем посты указанных категорий с главной страницы
  16.       if (in_array('home', $target) && $query->is_home) {
  17.         $query->set('cat',$cat_string);
  18.       }
  19.     }
  20.   }
  21.   return $query;
  22. }

* This source code was highlighted with Source Code Highlighter.

Исключить ненужные категории можно с помощью метода set.
Например:

$query->set('cat', '-1,-2,-5');

Здесь 1, 2, 5 – id категорий в БД, знак минус означает, что категории нужно исключить.

Обратите внимание. UPD. Плагин обновлен для использования с WP 3.1.
Теперь используется параметр. В качестве значения передается исходный архив с категориями, которые нужно исключить

$query->set('category__not_in',$categories);

В самой функции ec_exclude мы проверяем, указаны ли страницы, с которых нужно убрать посты и список ненужных категорий (с помощью get_option('cats_home') и get_option('cats_list')).

Если эти опции установлены, то формируем строку с id категорий $cat_string и передаём её методу set. При этом с $query->is_home и помощью $query->is_feed проверяем, какая страница в данный момент формируется.

Не зависимо от того, вносили мы изменения в запрос или нет, функция ec_exclude обязательно должна вернуть объект $query, иначе сформировать страницу не получится.

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

Все замечания, вопросы и предложения пишите в комментариях. Постараюсь ответить 😉

  • интересно, возьму себе на вооружение!

  • интересно, возьму себе на вооружение!

  • Отличный пост, сделал RT. Но есть один моральный нюанс, — заметил, что некоторые блогеры пропагандируют ставить продажные ссылки и статьи , закрывая их подобными плагинами. Ваше личное отношение к подобной практике?

    • У меня нормальное к этому отношение.
      Реклама на блогах присутствует практически всегда, даже если это реклама услуг самого автора или способ заработать авторитет.
      Поэтому не вижу ничего плохого в том, что кто-то размещает статьи за деньги.
      Если автор пишет интересные для меня статьи, то я их читаю. Если среди них будет реклама, то я ее пропущу. Если рекламы будет очень много, то, возможно, отпишусь от блога (хотя такого еще не было 🙂 )

  • Отличный пост, сделал RT. Но есть один моральный нюанс, — заметил, что некоторые блогеры пропагандируют ставить продажные ссылки и статьи , закрывая их подобными плагинами. Ваше личное отношение к подобной практике?

    • У меня нормальное к этому отношение.
      Реклама на блогах присутствует практически всегда, даже если это реклама услуг самого автора или способ заработать авторитет.
      Поэтому не вижу ничего плохого в том, что кто-то размещает статьи за деньги.
      Если автор пишет интересные для меня статьи, то я их читаю. Если среди них будет реклама, то я ее пропущу. Если рекламы будет очень много, то, возможно, отпишусь от блога (хотя такого еще не было 🙂 )

  • Хороший плагин, думаю он мне пригодится! Спасибо! А к рекламе я тоже отношусь нормально, главное чтобы блоги не были ней перегружены!

  • Хороший плагин, думаю он мне пригодится! Спасибо! А к рекламе я тоже отношусь нормально, главное чтобы блоги не были ней перегружены!

  • Хороший плагин, но вот реклама иногода сильно напрягает!

  • Хороший плагин, но вот реклама иногода сильно напрягает!

  • Да плагин действительно хорош!

  • Да плагин действительно хорош!

  • Игорь

    Если бы без рекламы, было бы замечательно!

  • Спасибо за помощь — это то что я искал и не знал как сделать. Ещё раз спасибо.

  • Спасибо, отличный плагин, искал что-то подобное!

  • WordPress является самым распространенным и популярным движком для блога. Очень универсален. Не подойдет разве что под очень узкие задачи. Сам ползуюсь и рекомендую. Автору спасибо за статью

  • Интересно, можно ли с помощью этого плагина убрать категорию Архив на блоге? У вас я вижу нет архивной рубрики. Мне она на нервы давит…

  • Скачала, установлю на свой страх и риск. Спасибо потом скажу…

  • Убрать можно любую категорию. Но, мне кажется, вы имеете ввиду не категорию, а блок с перечнем месяцев и количеством записей в них. Он создается либо с помощью виджета (т.е. его можно убрать из админке на странице управления виджетами), либо с помощью php кода в файле sidebar.php (этот файл находится в папке с вашей темой).

  • Very vivid appearance, perfect plot, challenging game. Many of us put this game as a very important part of life. Surprise,when I browse the web ,I found these website Pretty good. adidas arenas Signature

  • Pingback: Вопросы и ответы по Wordpress - выпуск 7()

  • Pingback: Как скрыть некоторые категории с главной страницы и из RSS | Exclude categories | n-wp.ru | темный Незнайка светлый Wordpress()

  • Pingback: Создание сайта. Разработка сайта. Киев, Оболонь » Post Topic » Плагин Exclude categories исключаем категории с главной и RSS()

  • Спасибо, лёгкий и понятный плагин — решила-таки не мудрить на этот раз с кодами, а использовать то, что уже есть!

  • Dasha

    подскажите, а как убрать ссылку на категорию еще и из Виджета «Категории» ?

    • Я не советую изменять стандартные виджеты WP, т.к. это придется делать после каждого обновления движка.

      Лучше используете AVH Extended Categories Widgets

  • Отличный плагин, но он и как варианты с function.php ^
    function myFeedExcluder($query) {
    if ($query->is_feed || $query->is_search) {
    $query->set('cat', '-29');
    }
    return $query;
    }
    add_filter('pre_get_posts','myFeedExcluder');

    Удаляет возможность подписки на RSS отдельных рубрик.

    • Согласен.
      Плагин работает примерно таким же образом.
      Только предоставляет интерфейс для удобного выбора категории, которую
      нужно исключить.

      • Я вижу, что так) Вопрос в том можно ли сохранить ОТДЕЛЬНЫЕ ленты для разных категорий? Что-то вроде http://САЙТ.ru/?feed=rss2&cat=5
        Теперь же все ленты подменяются на одну единственную, общую.
        Хочется решения….
        Спасибо

        •  А не подскажете как решили вопрос? Точно такая же проблема, нужно чтобы отдельные ленты для отдельных категорий сохранились.

        • Идея такая
          $query->set('cat', '-1,-2,-5');
          удалит категории с ID = 1, 2 и 5.

          Например, нужно чтобы для категории 5 в ленте были посты всех категорий. Добавляем условие

          if ($_GET['cat'] != 5) {$query->set('cat', '-1,-2,-5');}

          теперь в ленте http://САЙТ.ru/?feed=rss2&cat=5 будут все категории

        • Не знаю, можно ли здесь ссылки оставлять, но попробую. Я воспользовался другим кодом и просто добавил еще два условия к плагину. Вот здесь подробно описал, если интересно — http://forum.life-trip.ru/discussion/27/ubiraem-rubriki-s-glavnoy-i-iz-rss-sohranyaya-rss-etih-rubrik

  • Спасибо вам за плагин. Как раз делает только две вещи, которые нужны, и ничего лишнего.

    Ставил Advanced Category Excluder, так он слишком навороченный, да еще к тому-же делает не то что надо (его секций недостаточно), плюс рушит блог на локалхосте.

  • Доброй ночи на версии вордпресс 3.1 плагин не работает.

    • Global

      Да, сегодня я тоже обнаружил, что все «продажные» посты вылезли в ленту, твиттер и,тд

    • Shishlena

      Да, и у меня тоже самое :((((((((((

    • Большое спасибо за то, что сообщили о проблеме. И прошу прощения за задержку.

      Я выложил исправленную версию плагина.

      • Global

        А подскажите еще пожалуйста, как обновить РСС? точнее удалить от туда некоторые посты которых больше нет или я не хочу чтоб они там были

        • Удалить посты можно используя их id или какой-нибудь другой параметр, например, в этом плагине используется категория.

          Дальше все просто.
          1) используете фильтр pre_get_posts.
          2) модифицируете запрос так, как вам нужно ($query)

  • Товарищ, спасибо большое. Все по-русски, все понятно. Единственный вариант, который мне помог)))
    Спасибо за плагин!

  • Tod

    Жаль, что там не было «напоминания» о новой версии, а то как-то не обратил на это внимания и обновил вп, а там бац вылезли сообщения, которые не должны были появляться)

    • Честно говоря, я не думал, что этот плагин приобретет какую-то популярность. Существуют аналоги с гораздо более широкими возможностями.

      Поэтому я не стал размещать этот плагин на официальном сайте. Из-за этого уведомления об обновлениях плагина не работают.

      Думаете, имеет смысл перенести этот плагин на оф. сайт?

      • Геннадий

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

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

  • Даша

    А у меня что-то все-равно не работает:((
    Старый удалила, новый поставила, а не работает! В чем может быть дело

    • Напишите, пожалуйста, какую версию WP вы используете. И, желательно, версию PHP и список установленных плагинов.

  • WordPress 3.1.
    Плагины вот — http://sheko.ru/wp-content/uploads/2011/03/4.jpg

    • У меня не получается воспроизвести ошибку. Попробуйте отключить плагины (по одному). С версией 3.1 я проверял, плагин работает.

  • Lunalin

    спасибо! это именно то, что мне сейчас надо!:)

  • Спасибо! Отличный плагин и не надо ничего вставлять в функции темы

  • Pingback: Плагин для Wordpress: Exclude Categories. Убрать категорию постов с главной страницы | LAAcrus's блог()

  • Скачал плагин. Буду использовать для работы с гогетлинкс, т.к. там не нужно чтобы комментировали. Остаётся открытым вопрос, а при подписке на почтовый ящик, также посты будут исключаться?

    • Каким образом реализована подписка? Через feedburner? Если да, то feedburner возмет содержимое RSS. Т.е. уберете посты из RSS и их не будет в рассылке.

      • Да, через feedburner. Плагин протестировал. Работает.

        • Ещё плагин One click close comments скачал, чтобы отключать комментарии у отдельных постов, тоже работает.

  • 7wander7

    Спасибо за плагин! Очень пригодился)

  • Спасибо за плагин!

  • Юля

    Спасибо за плагин, то что надо. На свой риск поставила на ВП 3.3.2. Вроде нормально работает. Думаю зря вы на оф.сайте не выкладываете.

  • Антон Суряпин

    Спасибо! Используем теперь плагин на сайте фотоновостей Belarusian News Photos — http://www.bnp.by/ — убираем с главной страницы «Анонсы». Раньше был Advanced Category Excluder, но из-за него (не поверите!) сайт постоянно отключался.

    • Почему не поверю? Поверю 🙂
      В Advanced Category Excluder очень много опций и настроек, поэтому не удивительно, что он потребляет дополнительные ресурсы.

  • ecotraveler.ru

    плагин хороший, рекламу бы еще удалить…

  • Юрий

    Спасибо автору за плагин. Единственный вопрос возник. Я исключил одну категорию, чтобы она не выводилась на главной, и с ней в сайдбаре перестали выводиться свежие записи из этой категории (стандартный виджет wordpress)/ Подскажите, есть ли способ сделать так, чтобы категория по прежнему не выводилась на главной, но в свежих записях выводились ссылки на записи этой категории?

    • Без переделки плагина или виджета сделать это не получится. Попробуйте использовать

      AVH Extended Categories Widgets в качестве замены стандартного виджета.