Шорткоды WordPress — это макросы вида , которые заменяются на HTML при выводе записи. Они удобны для вставки динамического контента: форм обратной связи, таблиц цен, блоков с кодом, кнопок CTA. Разберём создание шорткодов от простых до вложенных, с параметрами и интеграцией в Gutenberg.
Создание простого шорткода
Функция add_shortcode() регистрирует шорткод. Первый аргумент — имя (только строчные буквы, цифры, дефис и подчёркивание), второй — callback-функция, которая возвращает HTML.
<?php
// functions.php — простой шорткод текущего года
add_shortcode( 'year', function() {
return date( 'Y' );
});
// Использование: Копирайт © [year]
// Шорткод с информацией о сайте
add_shortcode( 'site_info', function( $atts ) {
$atts = shortcode_atts([
'field' => 'name',
], $atts, 'site_info' );
switch ( $atts['field'] ) {
case 'name':
return get_bloginfo( 'name' );
case 'url':
return home_url();
case 'description':
return get_bloginfo( 'description' );
case 'posts_count':
return wp_count_posts()->publish;
default:
return '';
}
});
// Использование: Сайт [site_info field="name"] содержит [site_info field="posts_count"] статей
Callback шорткода должен возвращать строку через return, а не выводить её через echo. Если использовать echo, контент появится в начале страницы, а не в месте вставки шорткода.
Параметры (атрибуты) шорткода
Функция shortcode_atts() объединяет пользовательские атрибуты со значениями по умолчанию. Третий аргумент — имя шорткода — позволяет фильтровать атрибуты через хук shortcode_atts_{shortcode}.
<?php
// Шорткод кнопки с настраиваемыми параметрами
add_shortcode( 'button', function( $atts ) {
$atts = shortcode_atts([
'url' => '#',
'text' => 'Подробнее',
'color' => 'blue',
'size' => 'medium',
'target' => '_self',
'class' => '',
], $atts, 'button' );
$classes = 'btn btn-' . esc_attr( $atts['color'] ) . ' btn-' . esc_attr( $atts['size'] );
if ( $atts['class'] ) {
$classes .= ' ' . esc_attr( $atts['class'] );
}
return sprintf(
'<a href="%s" class="%s" target="%s">%s</a>',
esc_url( $atts['url'] ),
$classes,
esc_attr( $atts['target'] ),
esc_html( $atts['text'] )
);
});
// Использование: [button url="https://example.com" text="Купить" color="green" size="large"]
// Шорткод вывода последних записей
add_shortcode( 'recent_posts', function( $atts ) {
$atts = shortcode_atts([
'count' => 5,
'category' => '',
'orderby' => 'date',
], $atts, 'recent_posts' );
$args = [
'post_type' => 'post',
'posts_per_page' => intval( $atts['count'] ),
'post_status' => 'publish',
'orderby' => sanitize_key( $atts['orderby'] ),
'order' => 'DESC',
];
if ( $atts['category'] ) {
$args['category_name'] = sanitize_text_field( $atts['category'] );
}
$query = new WP_Query( $args );
if ( ! $query->have_posts() ) {
return '<p>Записей не найдено.</p>';
}
$output = '<ul class="recent-posts-shortcode">';
while ( $query->have_posts() ) {
$query->the_post();
$output .= sprintf(
'<li><a href="%s">%s</a> <span class="post-date">%s</span></li>',
get_permalink(),
get_the_title(),
get_the_date()
);
}
$output .= '</ul>';
wp_reset_postdata();
return $output;
});
// Использование: [recent_posts count="3" category="wordpress" orderby="comment_count"]
Все атрибуты приходят как строки — не забывайте приводить типы: intval() для чисел, filter_var() для boolean. Экранируйте вывод через esc_attr(), esc_html(), esc_url() — шорткоды могут использоваться в произвольном контексте.
Вложенные (enclosing) шорткоды
Вложенный шорткод оборачивает контент: [shortcode]содержимое[/shortcode]. Callback получает контент вторым аргументом $content.
<?php
// Шорткод для блока с предупреждением
add_shortcode( 'alert', function( $atts, $content = '' ) {
$atts = shortcode_atts([
'type' => 'info', // info, warning, danger, success
], $atts, 'alert' );
// do_shortcode() обрабатывает вложенные шорткоды внутри $content
$inner = do_shortcode( $content );
return sprintf(
'<div class="alert alert-%s">%s</div>',
esc_attr( $atts['type'] ),
wpautop( $inner ) // автоматические абзацы
);
});
// Использование:
// [alert type="warning"]
// Внимание! Этот код удалит все данные.
// [button url="/docs" text="Читать документацию"]
// [/alert]
// Шорткод спойлера (скрытый контент)
add_shortcode( 'spoiler', function( $atts, $content = '' ) {
$atts = shortcode_atts([
'title' => 'Показать',
], $atts, 'spoiler' );
static $spoiler_id = 0;
$spoiler_id++;
$output = '<div class="spoiler-wrap">';
$output .= '<button class="spoiler-toggle" onclick="document.getElementById(\'spoiler-' . $spoiler_id . '\').classList.toggle(\'spoiler-open\')">';
$output .= esc_html( $atts['title'] );
$output .= '</button>';
$output .= '<div id="spoiler-' . $spoiler_id . '" class="spoiler-content">';
$output .= do_shortcode( $content );
$output .= '</div></div>';
return $output;
});
// Использование: [spoiler title="Показать ответ"]Ответ: 42[/spoiler]
Важные нюансы вложенных шорткодов:
- WordPress не поддерживает вложенность одинаковых шорткодов:
[alert][alert]...[/alert][/alert]не сработает - Если
$contentсодержит другие шорткоды, вызывайтеdo_shortcode($content)для их обработки - Функция
wpautop()преобразует переносы строк в теги<p>— полезно для многострочного контента
Подключение стилей и скриптов только при использовании шорткода
Не подключайте CSS и JS глобально, если они нужны только для шорткода. Используйте wp_enqueue_style() и wp_enqueue_script() прямо в callback — WordPress подключит их в футере.
<?php
add_shortcode( 'price_table', function( $atts ) {
// CSS подключится только на страницах, где используется шорткод
wp_enqueue_style(
'price-table-css',
get_template_directory_uri() . '/assets/css/price-table.css',
[],
'1.0'
);
wp_enqueue_script(
'price-table-js',
get_template_directory_uri() . '/assets/js/price-table.js',
[ 'jquery' ],
'1.0',
true // в футер
);
$atts = shortcode_atts([
'columns' => 3,
], $atts, 'price_table' );
ob_start();
include get_template_directory() . '/template-parts/price-table.php';
return ob_get_clean();
});
Обратите внимание на приём с ob_start() / ob_get_clean() — он позволяет использовать PHP-шаблон с обычным HTML вместо конкатенации строк. Это намного удобнее для сложной вёрстки.
Интеграция шорткодов с Gutenberg
Начиная с WordPress 5.0, блочный редактор Gutenberg поддерживает шорткоды через блок «Шорткод». Но пользоваться им неудобно — нет предпросмотра и подсказок. Лучше создать собственный блок-обёртку:
<?php
// functions.php — регистрация блока для шорткода alert
add_action( 'init', function() {
// Проверяем, что Gutenberg доступен
if ( ! function_exists( 'register_block_type' ) ) {
return;
}
wp_register_script(
'alert-block-editor',
get_template_directory_uri() . '/blocks/alert/editor.js',
[ 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components' ],
'1.0'
);
register_block_type( 'mytheme/alert', [
'editor_script' => 'alert-block-editor',
'render_callback' => function( $attributes, $content ) {
$type = $attributes['type'] ?? 'info';
return sprintf(
'<div class="alert alert-%s">%s</div>',
esc_attr( $type ),
wpautop( do_shortcode( $content ) )
);
},
'attributes' => [
'type' => [
'type' => 'string',
'default' => 'info',
],
],
]);
});
Такой блок будет отображаться в визуальном редакторе с предпросмотром, а для вывода на фронте использует ту же логику, что и шорткод.
Типичные ошибки при создании шорткодов
- echo вместо return — самая частая ошибка. Контент появляется вверху страницы, а не в месте вставки. Используйте
ob_start()+ob_get_clean(), если нужно буферизировать вывод - Отсутствие экранирования — атрибуты шорткода могут содержать произвольный текст. Всегда экранируйте через
esc_attr(),esc_html(),esc_url() - Одинаковые имена — если два плагина зарегистрируют шорткод с одним именем, сработает тот, что зарегистрирован последним. Используйте уникальные префиксы:
[myprefix_button]вместо[button] - Тяжёлые запросы — шорткод выполняется при каждом просмотре страницы. Для сложных выборок используйте Transients API для кеширования
- Забыли
do_shortcode($content)— без этого вызова шорткоды внутри вложенного контента не обработаются
Шорткоды остаются удобным инструментом для вставки динамического контента, несмотря на появление Gutenberg-блоков. Они работают в классическом редакторе, виджетах (через add_filter('widget_text', 'do_shortcode')) и даже в PHP-шаблонах через do_shortcode('[your_shortcode]'). Главное — не злоупотребляйте ими: если логику можно вынести в шаблон темы или блок Gutenberg, это будет более производительно и поддерживаемо.
