Skip to content
⚡ Как добавить свой шорткод в WordPress: примеры и код

⚡ Как добавить свой шорткод в 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):

1function 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. Корректный способ, обернуть в хук:
1add_action( 'init', 'my_register_shortcodes' );
2
3function my_register_shortcodes() {
4 add_shortcode( 'mytag', 'my_shortcode_callback' );
5}
  • Префикс, обязательно. Глобальный массив один на все плагины и тему. Назвали шорткод [button], и ваш [button] молча перезаписал такой же шорткод из плагина форм. Префикс вроде myplugin_ или уникального сокращения решает проблему. В примерах ниже я использую префикс mysite_, в реальном проекте замените на свой.

Шаг 1: простой шорткод без параметров

Самый короткий путь к рабочему шорткоду, три строчки в functions.php дочерней темы (или в плагине Code Snippets, так безопаснее, не потеряется при обновлении темы).

Добавьте этот код и сохраните:

1add_shortcode( 'mysite_current_year', 'mysite_display_current_year' );
2
3function 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: шорткод с атрибутами

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

1add_shortcode( 'mysite_cta', 'mysite_cta_button' );
2
3function 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. Типовой сценарий, стилизованный блок с предупреждением:

1add_shortcode( 'mysite_notice', 'mysite_notice_box' );
2
3function 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
9defined( 'ABSPATH' ) || exit;
10
11class 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
39MySite_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 может быть ещё не готов к приёму новых тегов.

Шорткод в теме против плагина: что выбрать

Критерий

functions.php темы

Отдельный плагин

Скорость старта

Быстрее - файл уже загружен

Чуть медленнее - отдельный файл

Переносимость

Привязан к теме

Работает с любой темой

Выживаемость при обновлении

Слетает при обновлении темы

Живёт независимо

Удобство правки

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 или мини-плагин. Кода в любом из примеров выше, меньше десяти строк. Освоив эти три паттерна (простой, с атрибутами, с вложенным контентом), вы закроете подавляющее большинство задач, под которые вообще пишут кастомные шорткоды.