Куда поместить мой код: в плагин или functions.php?
Существует ли простая для понимания схема того, какой код должен находиться в плагине, а какой в файле functions.php
темы?
Есть множество различных случаев и дискуссий на эту тему, в основном из-за некоторых заблуждений о внутреннем устройстве WordPress. Я прошу ответ, основанный на фактах, а не на мнениях.
Необходимо объяснить, как обрабатывать следующие пункты (и возможно другие):
- пользовательские типы записей и таксономии
- контактные формы
- шорткоды
- пользовательские виджеты
add_theme_support( 'automatic-feed-links' );
- SEO функции, такие как пользовательские элементы
meta
- смена темы
Часто есть аргументы за и против обоих вариантов. Наш самый популярный вопрос Лучшая коллекция кода для вашего файла functions.php получил много фрагментов кода в качестве ответов, которые как минимум спорны.
Нам нужны критерии, которые сможет понять начинающий, возможно, контрольный список – с объяснениями.
Смотрите также связанный вопрос от Chip Bennett на нашем мета-сайте: Вопросы, специально запрашивающие решение "без плагина"
Связанные темы: Куда поместить фрагменты кода, которые я нашел здесь или где-то еще в интернете?
Я бы начал с такого вопроса: Связана ли функциональность с отображением контента, или с созданием/управлением контентом, сайтом или идентичностью пользователя?
Если функциональность не связана конкретно с отображением контента, то она однозначно относится к сфере плагинов. Вот неполный список примеров:
- Изменение основных фильтров WP (содержимое
wp_head
, например канонические ссылки, мета-теги generator и другие HTML-метаданные) - Фавикон сайта
- Шорткоды в контенте записей
- Кнопки "поделиться" для записей
- Скрипты в подвале сайта для Google Analytics и аналогичных сервисов
- Инструменты/настройки SEO
- и т.д.
Если функциональность связана с отображением контента, то она может быть включена в тему. В этом случае я бы применил критерий смены темы от @Raf912: будете ли вы скучать по этой функциональности при смене темы? Если ответ на этот вопрос нет, то функциональность принадлежит теме. Некоторые примеры:
- Удаление/переопределение CSS галереи из ядра WP
- Фильтрация длины анонса, текста "читать далее" и т.п.
- Любая функциональность, реализованная через
add_theme_support()
(это, полагаю, должно быть очевидно) - Пользовательские CSS-стили
Обычно эти два вопроса дают достаточно четкую границу раздела, но есть исключения.
Пользовательские типы записей
Пользовательские типы записей (Custom Post Types) представляют собой уникальный гибрид создания контента и его отображения, учитывая работу иерархии шаблонов для страниц архивов отдельных типов записей и страниц отдельных записей. Аспект создания контента обычно относит CPT к сфере плагинов, однако плагины не могут определять шаблоны страниц, которые органично вписываются в дизайн/макет/стиль любой данной темы (особенно если CPT отображает что-то помимо стандартных Заголовка/Контента/Метаданных или имеет связанные пользовательские таксономии).
В долгосрочной перспективе решением этого несоответствия, ИМХО, было бы создание стандартной конвенции/консенсуса по определению CPT для определенных типов контента (объявления о недвижимости, события календаря, товары интернет-магазинов, записи библиотеки книг/медиа и т.д.). Таким образом пользовательский контент оставался бы переносимым между темами, реализующими стандартное определение данного CPT, а разработчики тем сохранили бы гибкость в определении дизайна/макета/стиля этого CPT в файлах шаблонов темы.
Ссылки на социальные сети
Аналогично, я бы обычно сказал, что ссылки на профили в соцсетях, ставшие практически повсеместными в современных темах, относятся к сфере плагинов, так как они не имеют отношения к отображению контента. Лучшим решением было бы определение этих профилей где-то в ядре, однако в настоящее время нет стандартного/общепринятого способа их определения. Где их лучше определять — в настройках сайта или для каждого пользователя? Если для пользователя, то метаданные какого пользователя должны отображаться в шаблоне? И т.д.
Так что опять же, в долгосрочной перспективе решением этого несоответствия было бы либо определение в ядре места хранения этих ссылок, либо выработка консенсуса среди разработчиков тем. А пока ничего не остается, кроме как продолжать определять их в каждой теме.

add_theme_support( 'automatic-feed-links' );
не относится к презентационным функциям. Но это требуется в руководстве по темам. Почему это необходимый риск потерять данную функциональность при смене темы?

Любая функциональность, реализованная через add_theme_support()
, может быть реализована только через тему. Использование add_theme_support( 'automatic-feed-links' )
в теме фактически гарантирует единообразный опыт при переходе между темами, поскольку генерируемые ссылки на RSS-ленты будут одинаковыми.

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

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

Думаю, на этот вопрос нет простого ответа, но мы могли бы создать блок-схему для принятия решения. Вот приблизительный набросок такой схемы, который можно и нужно расширять. Делитесь предложениями в комментариях!
- Будет ли этот код размещаться на одиночном сайте WordPress?
- Да - Меняется ли тема сайта только при крупных редизайнах и изменениях функциональности?
- Да - Является ли рассматриваемый код специфичным для текущего дизайна?
- Да: functions.php
- Нет: Плагин
- Нет (тема меняется часто или по желанию) - Плагин
- Да - Является ли рассматриваемый код специфичным для текущего дизайна?
- Нет (Multisite) - Размещаете ли вы мультисайт самостоятельно ИЛИ это хостинг-решение для мультисайтов, позволяющее использовать плагины?
- Да: Является ли функциональность специфичной для этого сайта, или она может/должна использоваться другими сайтами сети?
- Специфична для этого сайта: functions.php
- Общая для нескольких сайтов - Хотите ли вы принудительно включить её на всех сайтах?
- Да: Плагин, размещённый в mu-plugins или активированный для всей сети
- Нет: Является ли это сетью не связанных между собой сайтов? (например, разных клиентов)
- Да: Будет ли это плохо или непрофессионально, если клиент A увидит или активирует плагин, написанный для клиентов B, C и D? (например, это может сломать сайт или вызвать нежелательную функциональность)
- Да: functions.php
- Нет: Плагин
- Нет: Скорее всего плагин
- Да: Будет ли это плохо или непрофессионально, если клиент A увидит или активирует плагин, написанный для клиентов B, C и D? (например, это может сломать сайт или вызвать нежелательную функциональность)
- Нет (хостинг-решение типа VIP, не позволяющее плагины): используйте functions.php
- Да: Является ли функциональность специфичной для этого сайта, или она может/должна использоваться другими сайтами сети?
- Да - Меняется ли тема сайта только при крупных редизайнах и изменениях функциональности?
- Родительские темы — иногда с общей функциональностью лучше создать родительскую тему и разместить код в functions.php родительской темы.
- Директории плагинов в крупных мультисайтовых инсталляциях могут быстро стать неуправляемыми, поэтому иногда общую функциональность, используемую небольшим процентом сайтов (например, < 1%), лучше дублировать в файлах functions.php.

Отсюда Темы VS Плагины
Добавляйте пользовательский код в дочернюю тему, чтобы при обновлении родительской темы ваш кастомный код не терялся.
Также вы можете создать сайт-специфичный плагин, который будет содержать весь ваш пользовательский код.
Что касается написания кода в сравнении с плагинами - вы можете использовать плагины и их функции, однако для большинства задач ручное кодирование предпочтительнее, так как его проще модифицировать. Исключение составляют такие случаи, как метабоксы, где стоит рассмотреть использование плагина, если вы не разработчик тем.
function modify_contact_methods($profile_fields) {
// Добавляем новые поля
$profile_fields['twitter'] = 'Twitter Username';
$profile_fields['facebook'] = 'Facebook URL';
$profile_fields['gplus'] = 'Google+ URL';
return $profile_fields;
}
add_filter('user_contactmethods', 'modify_contact_methods');
http://codex.wordpress.org/Plugin_API/Filter_Reference/user_contactmethods
- Добавить новый пользовательский тип записи - Код
- Добавить новые поля для пользователей - Код выше
- Добавить новые виджеты - Код
- Добавить пользовательские постоянные ссылки - Настройки постоянных ссылок WordPress

Я знаю, что это избитая тема, и Chip уже хорошо её осветил, но хотел добавить несколько мыслей.
Если вы зарабатываете программированием и работаете над сайтами на WordPress в условиях дедлайнов, вы поймёте, что всё сводится к вопросу времени.
Чаще всего, особенно для начинающих, гораздо быстрее и проще просто добавить нужный функционал прямо в тему и считать задачу выполненной.
Тем не менее, если вы работаете с WordPress на регулярной основе, вам стоит серьёзно задуматься о следующем:
- Создайте каркас плагина
Он должен включать всё, что обычно требуется в плагинах: активацию, деактивацию, обновление версий, создание админ-панелей и удаление.
Если вы выделите на это время, то обнаружите:
- Добавление функционала через плагины перестанет занимать много времени
- Вы сможете создать набор плагинов для повторного использования в других проектах, что в долгосрочной перспективе сэкономит вам массу времени
- Вы можете сделать их публично доступными, если хотите повысить свою видимость
Теперь вы можете разрабатывать правильно и быстрее завершать будущие проекты.
- Создайте каркас темы
Он должен включать всё, что обычно требуется в теме:
- Основную таблицу стилей с часто используемыми стилями (сбросы и т.д.)
- Правильный файл index.php, обрабатывающий всё необходимое для любого шаблона
- Файл functions.php — он понадобится не так часто, но всё равно будет полезен
После этого создайте каркас дочерней темы, использующей вашу основную тему.
- Добавьте таблицу стилей, ссылающуюся на родительскую тему
- Добавьте файл functions.php
Сделав эти две вещи, вы заметите, что создание новых сайтов станет гораздо быстрее.
Если вы выполните вышеперечисленное, сможете заняться следующим:
- Потратьте освободившееся время на углубление знаний PHP, WordPress, JavaScript, CSS и/или mySQL — чем больше вы знаете, тем быстрее будете работать.
- Обновляйте каркасы плагинов, тем и дочерних тем по мере обнаружения улучшений. Независимо от вашего уровня, если вы продолжаете учиться, вы всегда найдёте, что можно улучшить.
И если вы сделаете всё вышеперечисленное, вы обнаружите, что ответ Chip станет не только идеальным, но и оптимальным решением.

Простой ответ таков..
Зависит ли код от какой-либо функциональности, встроенной в конкретную тему? Если да, то разместите его в теме.
Хотите ли вы, чтобы этот код можно было переносить между сайтами и темами? Если да, то разместите его в плагине.
Если ответ на оба вопроса отрицательный, представьте сайт через 5 лет, когда придет время для редизайна. Останется ли функциональность вашего кода актуальной после следующего обновления дизайна? Если да, разместите его в плагине.
Также, если вы не используете дочерние темы и планируете обновлять основную тему, я также рекомендую использовать плагин.

В ответ автору:
Пользовательские типы записей и таксономии
Должны находиться в плагине, так как они определяют структуру/концепцию, а не представление
Контактные формы
Относятся к представлению и должны быть в functions.php темы
Шорткоды
В плагине, так как являются структурными элементами
Пользовательские виджеты
Являются частью представления и должны находиться в functions.php темы
add_theme_support( 'automatic-feed-links' );
Поддержка темы относится к functions.php темы
SEO-функции, такие как пользовательские мета-элементы
Относятся к представлению, поэтому в functions.php
