Мой сайт о WordPress и PHP С Днем победы!
9 декабря 2007

Отображение виджетов в сайдбарах при разных условиях

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

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

Перед тем, как продолжить, я еще больше усложню задачу. Предположим нам нужно выводить виджеты так:

  • Календарь - только на главной странице
  • Архив только на страницах обычных записей
  • RSS только на постоянной странице с короткой ссылкой «myrss»
  • Облако меток на всех кроме главной
  • Рубрики - только на постоянных страницах и главной

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

Чтобы решить такую задачу, нужно знать как WordPress вообще выводит виджеты. Для многих это некие «черные ящички», но на самом деле это самые обычные php-функции. Просто вызываются они автоматически после того, как выполняется их активация в админ-панели.

К особенностям виджетов следует отнести еще и способ их настройки. Причем, то как это делается в виджетах, когда-то задумывалось как способ хранения настроек для всех подключаемых модулей. Происходит это по следующей схеме:

  • Есть таблица в базе данных, которая служит для хранения пары «ключ=значение». Причем «значение» может быть разных типов, например массивом.
  • Настройка виджета выполняется отдельной функцией. Функция использует и модифицирует настройки для своего виджета. То есть после того, как вы изменили, например заголовок виджета, данные попадают в базу данных.
  • Функция виджета (которая непосредственно выводит данные на странице) в начале считывает нужные настройки из базы и уже по ним определяет что и как нужно выводить.

Естественно это упрощенный алгоритм и WordPress предоставляет вспомогательные функции для работы с базой. Поэтому вместо SQL-запроса функция использует две основные функции:

  • get_option('ключ'); // получить данные по этому ключу
  • update_option('ключ', $options); // обновить данные

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

То есть теперь мы подходим к главному: поскольку задублировать виджеты мы не можем, но никто нам не мешает использовать функции виджетов сколько угодно раз!

Однако теперь несколько меняется значение страницы «Виджеты» в админ-панели. На ней можно будет настроить сами виджеты, но их порядок (и расположение на сайдбаре) никоим образом не будет влиять на реальный вывод.

Сделаем небольшую заготовку, чтобы понять как это будет выглядеть на практике.

Создадим (изменим) файл functions.php (находится в каталоге шаблона):

<?php
register_sidebar(array(
	'name' => 'Настроки виджетов',
	'before_widget' => '',
	'after_widget' => '',
	'before_title' => '',
	'after_title' => '')
);
?>

То есть мы регистрируем один-единственный сайдбар, даже если у вас в шаблоне их два, три или десять.

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

<?php
# множественные виджеты, где можно указать номер виджета
wp_widget_rss(array(), 1); // RSS
wp_widget_text(array(), 1); // текстовый
wp_widget_categories(array(), 1); // рубрики

# одиночные виджеты
wp_widget_tag_cloud(array()); // облако меток
wp_widget_recent_comments(array()); // последние комментарии
wp_widget_recent_entries(array()); // последние записи
wp_widget_archives(array()); // архивы
wp_widget_pages(array()); // постоянные страницы
wp_widget_links(array()); // ссылки
wp_widget_search(array()); // форма поиска
wp_widget_meta(array()); // управление
wp_widget_calendar(array()); // календарь
?>

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

Теперь, если обновить сайт, то увидите в сайдбаре все виджеты. Причем настроить их можно будет в админ-панели.

Один нюанс. Если вы используете плагины, которые создают свои виджеты, то вам придется искать в них нужные функции и вручную прописывать в sidebar.php.

Теперь, думаю, вы уже догадались, что совершенно несложно модифицировать наш sidebar.php под нужные условия. В нашем случае это примерно так:

//Календарь - только на главной странице
if ( is_home() ) wp_widget_calendar(array()); // календарь

//Архив только на страницах обычных записей
if ( is_single() ) wp_widget_archives(array()); // архивы

//RSS только на постоянной странице с короткой ссылкой «myrss»
if ( is_page('myrss') ) wp_widget_rss(array(), 1); // RSS

//Облако меток на всех кроме главной
if ( !is_home() ) wp_widget_tag_cloud(array()); // облако меток

//Рубрики - только на постоянных страницах и главной
if ( is_home() or is_page() )
	wp_widget_categories(array(), 1); // рубрики

Если у вас используются два сайдбара, то мы просто дублируем файл sidebar.php во второй файл и в нем прописываем функции виджетов.

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

Например, мы теряем возможность менять порядок виджетов через админ-панель. Нельзя назвать это глобальной катастрофой, поскольку обычно сайт настраивается один раз и надолго. С другой стороны эта проблема частично решаема, если воспользоваться плагином «Ушки».

Суть его в том, чтобы в файле сайдбара (sidebar.php) прописать вызов ушки (с префиксом «php_»!). Таким образом, сайдбар будет просто запускать указанную ушку. Соответственно функции виджетов и их кастомизацию мы прописываем уже в ушке и настроить отображение виджетов можно прямо через админ-панель. Это хоть и не так наглядно, но отчасти решает проблему.

При этом нам достаточно столько ушек, сколько используется сайдбаров.

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

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

google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru

7 комментариев к “Отображение виджетов в сайдбарах при разных условиях”

  1. molse:

    Давно думал как бы реализовать что-то подобное, но придумать не смог. Спасибо! :cool:

  2. granvik:

    По-моему стратегически неверное решение. Шаг назад к безвиджетному WordPress. Раз уж править sidebar.php, то тогда всё можно в него и поместить, обойтись без виджетов. По-моему, если необходимо отображать виджет не на всех страницах, то можно поправить его код, добавив те же условия, тогда не исчезает смысл виджетизации. А наиболее правильным мне кажется попросить разработчиков добавить подобный функционал в движок, он будет востребован.

  3. Максим:

    Ну стратегически может и не правильно, зато тактически верно. ;) Если вообще все перенести в файл сайдбара, то исчезает и возможность самой настройки виджетов.

    Альтернатива в принципе тоже есть - использовать сторонние виджеты или разрабатывать свои. Благо это не так и сложно. Но верить, что этим будут заниматься разработчики WordPress - утопия.

  4. cross:

    Поставил себе тему бе поддержки виджетов в сайдбаре...

    Мало того, что пришлось этот сайдбар сделать, так еще и каждый виджет настроить под себя заново пришлось. Так что не такая уж это и утпия.

  5. ScorpAL:

    Возможно кому-то в чем-то поможет

    Duplicate Sidebar Widgets Plugin
    http://www.lancelhoff.com/2007/08/29/wordpress-duplicate-sidebar-widgets/

  6. CyberMax:

    Спасибо за пост.
    Для меня действительно устройство сайдбаров и виджетов было неизвестно. Когда ставил какую нибуть новую тему и нажав на кнопку Виджеты появлялось Сайдбары не определены забивал на эту тему даже если она очень нравилась.
    Теперь думаю смогу исправить понравившуюся мне тему.

  7. nicothin:

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

    у меня выведенные описанным выше способом виджет не включает в себя то, что прописано в «before_widget» и др. параметрах в function.php, в результате заголовок выводится неформатированным текстом, после которого тупо идет содержимое.

    скажем:

    метки [ссылка 1] [ссылка 2] и т.п. - то есть ни контейнера-коробки, ни форматирования содержимого...

    я, наверное, чтото не понимаю (y., я в вордпрессе, покачто), или способ неюзабелен?


Оставьте комментарий! (Вы согласны с правилами)

 

:mrgreen: :neutral: :twisted: :arrow: :shock: :smile: :???: :cool: :evil: :grin: :idea: :oops: :razz: :roll: :wink: :cry: :eek: :lol: :mad: :sad: :!: :?:

При добавлении кода (html, php) заменяйте < на &lt; и > на &gt;.
Внимание: антиспам - зверь! Копируйте своё сообщение перед отправкой. На всякий случай.