
⚡ Как добавить свой шорткод в WordPress: примеры и код
Нужно вывести дату последнего обновления поста в подвале каждой статьи. Или вставить форму подписки ровно посередине текста, без редактора кода и танцев с шаблонами. В WordPress для этого есть шорткоды.
Шорткод — это короткий тег в квадратных скобках: [myshortcode]. WordPress находит его в контенте и подменяет на результат PHP-функции. Стандартные шорткоды вроде [gallery] и [embed] вы используете постоянно, даже не задумываясь. Но свой шорткод — это рычаг: один раз написал логику, а редактор вставляет её куда угодно тремя нажатиями.
За 10 минут вы создадите первый рабочий шорткод: от пустой функции до тега с атрибутами и вложенным контентом. Код реальный, запускается на любом современном WordPress, проверен на тестовом сайте.
💡 Быстрый обзор:
- Функция
add_shortcode: что принимает и как устроена изнутри - Базовый шорткод
[current_year], текущий год в тексте - Шорткод с атрибутами
[cta text="Скачать"], кастомная кнопка - Шорткод с вложенным контентом
[notice]Текст[/notice], стилизованный блок - Подключение через плагин или
functions.php: плюсы и минусы каждого способа - Типовые ошибки:
echoвместоreturn, конфликт имён, пустой атрибут в PHP 8+
Что умеет add_shortcode и как она работает
Функция add_shortcode, единственный штатный способ зарегистрировать новый шорткод в WordPress. Она принимает два параметра:
$tag(string), имя шорткода, которое вы будете писать в квадратных скобках. Только буквы, цифры и подчёркивания. Пробелы и спецсимволы& / < > [ ] =запрещены, WordPress молча откажется регистрировать такой тег.$callback(callable), имя PHP-функции, которая сработает при обнаружении шорткода. Именно она формирует тот HTML, который увидит посетитель.
Исходный код функции, пять строк логики и две проверки на дурака (полный листинг на developer.wordpress.org):
1 function add_shortcode( $tag, $callback ) { 2 global $shortcode_tags; 3 4 if ( '' === trim( $tag ) ) { 5 _doing_it_wrong( 6 __FUNCTION__, 7 __( 'Invalid shortcode name: Empty name given.' ), 8 '4.4.0' 9 ); 10 return; 11 } 12 13 if ( 0 !== preg_match( '@[<>&/\[\]\x00-\x20=]@', $tag ) ) { 14 _doing_it_wrong( 15 __FUNCTION__, 16 sprintf( 17 /* translators: 1: Shortcode name, 2: Space-separated list of reserved characters. */ 18 __( 'Invalid shortcode name: %1$s. Do not use spaces or reserved characters: %2$s' ), 19 $tag, 20 '& / < > [ ] =' 21 ), 22 '4.4.0' 23 ); 24 return; 25 } 26 27 $shortcode_tags[ $tag ] = $callback; 28 }
Ключевой момент: $shortcode_tags, глобальный массив. WordPress хранит в нём все зарегистрированные шорткоды. При рендеринге контента ядро проходит по этому массиву и для каждого найденного тега вызывает связанную функцию. Отсюда два следствия:
- *Регистрируйте на хуке
init.* Если повеситьadd_shortcodeнапрямую в файле плагина, она может сработать до полной инициализации WordPress. Корректный способ, обернуть в хук:
1 add_action( 'init', 'my_register_shortcodes' ); 2 3 function my_register_shortcodes() { 4 add_shortcode( 'mytag', 'my_shortcode_callback' ); 5 }
- Префикс, обязательно. Глобальный массив один на все плагины и тему. Назвали шорткод
[button], и ваш[button]молча перезаписал такой же шорткод из плагина форм. Префикс вродеmyplugin_или уникального сокращения решает проблему. В примерах ниже я использую префиксmysite_, в реальном проекте замените на свой.
Шаг 1: простой шорткод без параметров
Самый короткий путь к рабочему шорткоду, три строчки в functions.php дочерней темы (или в плагине Code Snippets, так безопаснее, не потеряется при обновлении темы).
Добавьте этот код и сохраните:
1 add_shortcode( 'mysite_current_year', 'mysite_display_current_year' ); 2 3 function mysite_display_current_year() { 4 return date( 'Y' ); 5 }
Теперь в любом посте или на странице напишите [mysite_current_year]. На фронте вместо шорткода отобразится текущий год: «2026».
Что здесь происходит. Функция mysite_display_current_year не принимает аргументов, вызывает PHP-функцию date('Y') и возвращает строку из четырёх цифр. WordPress подставляет эту строку ровно в то место, где стоял шорткод. Никакой магии.
Где это применить на практике: год в футере (© [mysite_current_year]), возраст проекта в тексте («работаем с [mysite_current_year] года»), автоматическое обновление дат в юридических страницах.
Шаг 2: шорткод с атрибутами
Шорткод без параметров полезен, но настоящая гибкость начинается с атрибутов. Классический пример, кнопка с настраиваемым текстом и ссылкой:
1 add_shortcode( 'mysite_cta', 'mysite_cta_button' ); 2 3 function mysite_cta_button( $atts ) { 4 $atts = shortcode_atts( 5 array( 6 'text' => 'Learn more', 7 'url' => '#', 8 ), 9 $atts, 10 'mysite_cta' 11 ); 12 13 return sprintf( 14 '<a href="%s" class="mysite-cta-button">%s</a>', 15 esc_url( $atts['url'] ), 16 esc_html( $atts['text'] ) 17 ); 18 }
В редакторе используйте так:
1 [mysite_cta text="Download plugin" url="https://example.com/myplugin/"]
Функция shortcode_atts делает три вещи разом: объединяет пользовательские атрибуты с дефолтными значениями, фильтрует только известные ключи и нормализует пустую строку в массив (без неё при вызове [mysite_cta] без атрибутов в PHP 8+ упадёт TypeError, первый параметр callback-функции получит пустую строку, а не массив).
*Почему esc_url и esc_html.* Шорткод вставляется редактором, сегодня это вы, а завтра контент-менеджер без доступа к коду. Экранирование на выходе страхует от случайного XSS, если в атрибут text попадёт скобка или тег.
Шаг 3: шорткод с вложенным контентом
Некоторые шорткоды оборачивают фрагмент текста: [mysite_notice]Важное сообщение[/mysite_notice]. Вложенный контент приходит в callback вторым параметром, $content. Типовой сценарий, стилизованный блок с предупреждением:
1 add_shortcode( 'mysite_notice', 'mysite_notice_box' ); 2 3 function mysite_notice_box( $atts, $content = null ) { 4 $atts = shortcode_atts( 5 array( 6 'type' => 'info', 7 ), 8 $atts, 9 'mysite_notice' 10 ); 11 12 $class = 'notice-' . esc_attr( $atts['type'] ); 13 14 return sprintf( 15 '<div class="mysite-notice %s"><p>%s</p></div>', 16 $class, 17 do_shortcode( $content ) 18 ); 19 }
Обратите внимание на do_shortcode( $content ). Если внутри вашего шорткода редактор вставил другой шорткод (например [mysite_current_year]), эта обёртка запустит и его. Без do_shortcode вложенные шорткоды отобразятся как текст в квадратных скобках, сырой [mysite_current_year] вместо «2026».
CSS для блока, минимальный, для начала:
1 .mysite-notice { 2 border-left: 4px solid #2271b1; 3 background: #f0f6fc; 4 padding: 1em 1.2em; 5 margin: 1.5em 0; 6 border-radius: 4px; 7 } 8 .mysite-notice.notice-warning { 9 border-left-color: #dba617; 10 background: #fcf9e8; 11 }
Добавьте стили в style.css дочерней темы или через Appearance → Customize → Additional CSS.
Шаг 4: шорткод внутри плагина (ООП-подход)
Когда шорткодов становится больше трёх, functions.php превращается в свалку. Пора выносить логику в отдельный плагин, а в идеале в класс. Вот заготовка мини-плагина с одним шорткодом:
1 <?php 2 /** 3 * Plugin Name: MySite Shortcodes 4 * Description: Custom shortcodes for the site. 5 * Version: 1.0.0 6 * Requires PHP: 7.4 7 */ 8 9 defined( 'ABSPATH' ) || exit; 10 11 class MySite_Shortcodes { 12 13 public static function init() { 14 add_action( 'init', array( __CLASS__, 'register' ) ); 15 } 16 17 public static function register() { 18 add_shortcode( 'mysite_email', array( __CLASS__, 'email_obfuscated' ) ); 19 } 20 21 public static function email_obfuscated( $atts ) { 22 $atts = shortcode_atts( 23 array( 'address' => '' ), 24 $atts, 25 'mysite_email' 26 ); 27 28 if ( ! is_email( $atts['address'] ) ) { 29 return ''; 30 } 31 32 return sprintf( 33 '<a href="mailto:%1$s">%1$s</a>', 34 antispambot( $atts['address'], 1 ) 35 ); 36 } 37 } 38 39 MySite_Shortcodes::init();
Поместите этот файл в wp-content/plugins/mysite-shortcodes/mysite-shortcodes.php и активируйте плагин в админке. Шорткод [mysite_email address="hello@example.com"] выведет защищённую от спам-ботов ссылку, функция antispambot кодирует символы email в HTML-entities.
Почему класс, а не набор функций. Пространство имён: три шорткода в классе не пересекутся со сторонними функциями. Плюс автозагрузка, плюс читаемый код, если плагин вырастет до десятка шорткодов.
Тестирование шорткода перед публикацией
После добавления кода проверьте три сценария:
- Шорткод без атрибутов. Просто
[mysite_cta], должен отрисоваться с дефолтными значениями (текст «Learn more», ссылка#). - Шорткод с атрибутами. Полный набор параметров, все значения подтянулись и отобразились корректно.
- Ошибка в атрибутах. Невалидный email в
[mysite_email], функция молча возвращает пустую строку, а не ломает страницу.
Важно: никогда не используйте echo внутри callback-функции. Шорткод должен возвращать строку через return. Если вывести HTML через echo, он появится не на месте шорткода, а в самом верху страницы, WordPress запускает рендеринг шорткодов до вывода контента. Та же логика, что у фильтров: функция отдаёт значение, движок сам решает, куда его вставить.
Второй нюанс: если шорткод не отображается (видите [mysite_cta] как текст, а не кнопку), проверьте, что функция зарегистрирована на хуке init, а не напрямую в теле плагина. Без init глобальный массив $shortcode_tags может быть ещё не готов к приёму новых тегов.
Шорткод в теме против плагина: что выбрать
Критерий |
| Отдельный плагин |
|---|---|---|
Скорость старта | Быстрее - файл уже загружен | Чуть медленнее - отдельный файл |
Переносимость | Привязан к теме | Работает с любой темой |
Выживаемость при обновлении | Слетает при обновлении темы | Живёт независимо |
Удобство правки | Appearance → Theme File Editor | Редактор плагинов или FTP |
Для скольких шорткодов | 1-3 | 4+ |
Правило: начали с functions.php на тестовом сайте, сделали три шорткода, выносите в плагин. Обновление темы через полгода не похоронит вашу логику, и перенести шорткоды на другой проект можно за минуту.
⁉️🤔 Частые вопросы
В чём разница между шорткодом и блоком Gutenberg?
Шорткод, текстовый тег в квадратных скобках, который обрабатывается на стороне сервера. Блок, визуальный компонент редактора, React-компонент с настройками в сайдбаре. Шорткоды появились в WordPress 2.5 (2008), блоки, в 5.0 (2018). Сегодня блоки, основной способ вставки динамического контента, но шорткоды остаются актуальными: они проще в разработке, не требуют знания JavaScript и работают в любом редакторе, включая Classic Editor и конструкторы страниц.
Шорткод — это текстовый тег, который WordPress заменяет на результат PHP-функции при выводе страницы. В отличие от блока Gutenberg, у шорткода нет визуального интерфейса в редакторе, контент-менеджер пишет
[myshortcode]текстом, а на фронте видит готовый HTML.
Можно ли использовать шорткод внутри другого шорткода?
Да. Если callback-функция внешнего шорткода оборачивает вложенный контент в do_shortcode(), внутренние шорткоды отработают корректно: [notice][current_year][/notice] выведет стилизованный блок с текущим годом. Без do_shortcode() вложенный шорткод останется текстом в квадратных скобках.
Вложенные шорткоды обрабатываются рекурсивно: WordPress проходит по строке несколько раз, пока не останется необработанных тегов. Но для этого внешний шорткод должен явно вызывать
do_shortcode($content). Иначе строка[current_year]так и останется текстом, а не превратится в «2026».
Почему мой шорткод не работает, отображается как текст в квадратных скобках?
Три частые причины. Первая: add_shortcode вызвана до хука init, перенесите регистрацию внутрь add_action('init', ...). Вторая: опечатка в имени тега, [my_shortcode] в редакторе, а зарегистрирован myshortcode. Третья: callback-функция использует echo вместо return, вывод улетает в начало страницы, а на месте шорткода пусто.
Чаще всего виноват
echoвместоreturnв callback-функции. WordPress вызывает обработчики шорткодов до вывода основного контента, результатechoпопадает в буфер вывода раньше, чем заголовок страницы. Откройте исходный код страницы (Ctrl+U): если видите HTML шорткода в самом верху, до<html>, проблема именно в этом.
Нужно ли экранировать вывод шорткода?
Обязательно. Шорткод принимает атрибуты от редактора, а значит, потенциально от любого пользователя с правами автора или редактора. esc_html() для текста, esc_url() для ссылок, esc_attr() для HTML-атрибутов. Исключение, если вы намеренно возвращаете HTML-разметку (как <div class="notice">). Но даже тогда атрибуты внутри разметки экранируйте.
Да, экранирование обязательно для всего, что приходит из атрибутов шорткода или пользовательского ввода. Даже если сегодня шорткоды вставляете только вы, завтра доступ к редактору получит контент-менеджер.
esc_html()для текста,esc_url()для ссылок,esc_attr()для HTML-атрибутов спасают от случайного или намеренного XSS.
Сколько шорткодов можно зарегистрировать на одном сайте?
Технического лимита нет, $shortcode_tags это обычный PHP-массив, упрётесь в память сервера сильно позже, чем в здравый смысл. На практике после 15-20 кастомных шорткодов стоит задуматься: а не пора ли часть из них перенести в блоки Gutenberg? Шорткоды с уникальной логикой (email-обфускация, условный вывод по роли), оставляйте. Шорткоды ради стилизации текста ([highlight]), лучше сделать стилем блока или CSS-классом.
Технически, сколько угодно, массив
$shortcode_tagsне имеет искусственного лимита. Практически, больше 20-25 шорткодов на одном сайте говорит о том, что часть логики пора переносить в блоки. Каждый шорткод добавляет накладные расходы на парсинг контента: перед выводом WordPress проходит по всему массиву зарегистрированных тегов и ищет совпадения в тексте поста.
Стоит ли писать свои шорткоды или хватит готовых плагинов?
Готовый плагин покрывает большинство типовых задач: формы, Contact Form 7, таблицы, TablePress, гриды, любой page builder. Свой шорткод нужен, когда логика специфична для вашего сайта и готового решения нет: вывод кастомного поля именно в этом месте страницы, дата следующего вебинара из базы, персонализированное приветствие по роли пользователя.
Если коротко: для типового функционала берите плагин и не программируйте. Для уникальной логики, add_shortcode + functions.php или мини-плагин. Кода в любом из примеров выше, меньше десяти строк. Освоив эти три паттерна (простой, с атрибутами, с вложенным контентом), вы закроете подавляющее большинство задач, под которые вообще пишут кастомные шорткоды.



