Я покажу вам, как я регистрирую шорткоды прямо в теме, доставляю их в безопасное место и отображаю в нужных местах - вот как я создаю тема wordpress с шорткодами с четкой структурой, чистым кодом и быстрой загрузкой. Я привожу практические примеры, объясняю do_shortcode в шаблоне, обсуждаю атрибуты, экранирование и кэширование, а также добавляю лучшие практики для долговременной поддерживаемой темы.
Центральные пункты
- Регистрация через функции обратного вызова add_shortcode и clear
- Интеграция в редакторе, в виджетах и в шаблонах с do_shortcode
- Безопасность с помощью экранирования, атрибутов и валидации
- Техническое обслуживание с дочерней темой, документацией и контролем версий
- Производительность с кэшированием, экономными запросами и аннулированием кэша
Шорткоды в теме: регистрация и структура
Я размещаю регистрацию в теме в разделе functions.php или в небольшом плагине, который необходимо использовать, если я хочу отделить функциональность от макета. Каждая функция обратного вызова возвращает строку и не использует echo, иначе вывод окажется в неожиданных местах. Я выбираю уникальные префиксы для именования, чтобы избежать конфликтов с плагинами. Так я сохраняю читаемость кода и создаю четкий порядок, например, /inc/shortcodes.php с целевым require_once в functions.php. Для начала достаточно простого шорткода приветствия, который впоследствии я буду расширять шаг за шагом.
<?php
// /wp-content/themes/my-theme/functions.php
require_once get_template_directory() . '/inc/shortcodes.php';
<?php
// /wp-content/themes/my-theme/inc/shortcodes.php
function my_greeting_shortcode() {
return 'Здравствуйте, добро пожаловать на мой сайт!
}
add_shortcode('greeting', 'my_greeting_shortcode');
Используйте шорткоды в шаблоне: do_shortcode
Я вызываю шорткоды в шаблоне с помощью do_shortcode когда я интегрирую контент в заголовки, колонтитулы или специальные шаблоны. Это позволяет сохранить чистоту редактора и держать повторяющиеся модули в центральном месте. Я документирую вызовы шаблонов в коде коротким комментарием, чтобы другие сразу знали, какой шорткод здесь используется. Для динамических параметров я создаю строку шорткода в PHP и передаю значения с безопасным экранированием. Этот метод работает в каждом файле шаблона, таком как header.php, footer.php или page-templates.
<?php
// В файле шаблона
echo do_shortcode('[приветствие]');
echo do_shortcode('[colorbox color="green"]Красивый текст[/colorbox]');
Атрибуты, содержание и безопасность
Я устанавливаю атрибуты с помощью shortcode_atts и защищайте значения с помощью esc_html, esc_attr и esc_url. Это предотвращает XSS и обеспечивает корректный HTML во всех выводах. Я дополнительно обрабатываю содержимое, заключенное в шорткод, с помощью wp_kses, если хочу разрешить только определенные теги. Для цветов я принимаю только значения из белого списка или проверяю их с помощью regex, чтобы не пропустить скрипты. Благодаря этим правилам шорткоды остаются надежными и выдают предсказуемый результат.
<?php
function my_colorbox_shortcode($atts, $content = null) {
$atts = shortcode_atts([
'color' => 'blue',
], $atts, 'colorbox');
$color = preg_match('/^#?[0-9a-fA-F]{3,6}$/', $atts['color']) ? $atts['color'] : 'blue';
$inner = wp_kses($content, ['strong' => [], 'em' => [], 'a' => ['href' => []]);
$style = 'background:' . esc_attr($color) . ';padding:10px';
return '<div style="' . $style . '">' . $inner . '</div>';
}
add_shortcode('colorbox', 'my_colorbox_shortcode');
Практические примеры: текущий год, кнопка и даты
Я использую небольшие вспомогательные шорткоды для повторяющегося контента, например, для текущего Годкнопки или списки из пользовательских типов постов. Шорткод на год избавляет меня от работы по обслуживанию в нижнем колонтитуле или в текстовых блоках. Я снабжаю кнопки текстом, URL и цветом, чтобы редакторы могли работать без изменения кода. Для вывода данных из CPT я ограничиваю запрос и кэширую результаты, чтобы страница оставалась быстрой. Вот три коротких фрагмента в качестве основы.
<?php
// Jahr
add_shortcode('current-year', function() {
return date('Y');
});
// Button
add_shortcode('button', function($atts) {
$atts = shortcode_atts([
'text' => 'click now',
'url' => '#',
'color' => '#2d89ef',
], $atts, 'button');
$text = esc_html($atts['text']);
$url = esc_url($atts['url']);
$color = esc_attr($atts['color']);
return '<a href="/ru/' . $url . '/" style="background:' . $color . ';padding:8px 18px;color:#fff;border-radius:4px;text-decoration:none">' . $text . '</a>';
});
Тема или плагин? Поддержка принятия решений и миграция
Я включаю шорткоды в Тема если они влияют на макет, и в плагине, если я хочу продолжать использовать их независимо от темы. Таким образом, я не теряю функции при смене темы и сохраняю ясность архитектуры. Для документации я создаю обзор всех шорткодов с параметрами, чтобы редакторы могли быстро найти правильный синтаксис. При последующем переносе я экспортирую файлы шорткодов и тщательно заменяю пути к ним. Следующая таблица помогает принять решение.
| Используйте | Тема | Плагин |
|---|---|---|
| Привязка к макету | Высокий (например, Hero-Box) | Низкий |
| Миграционный риск | Выше с изменением темы | Низкийсохраняется |
| Обслуживание/обновления | С выходом темы | Собственный выпуск, более гибкий |
| Целевая группа | Особенности макета | Содержание/Функции |
Использование шорткодов в редакторе и в редакторе блоков
Я добавляю шорткоды в классическом редакторе непосредственно как Текст и используйте блок шорткодов в редакторе блоков. Такое разделение сохраняет ясность контента и уменьшает количество ошибок при копировании. Для редакторов я документирую примеры непосредственно в бекенде, например, в виде блока-образца или заметки в шаблоне. Я обращаю внимание на различия между редакторами в интервалах и инлайн-стилях, поскольку блоки иногда добавляют дополнительные обертки. Если вы раздумываете над выбором редактора, то в сравнении вы найдете Редактор блоков против классического полезные советы.
Производительность: кэширование и чистые запросы
Я поддерживаю быстродействие шорткодов, кэшируя части, требующие больших вычислений, и ограничивая доступ к данным, что уменьшает Время загрузки низкие. Для повторяющихся проблем я использую Transients или WP Object Cache со значимым ключом. Я ограничиваю запросы с помощью posts_per_page, устанавливаю только необходимые поля и избегаю дорогостоящих операций COUNT. Я добавляю ширину/высоту и ленивую загрузку к выводам изображений, чтобы страница быстрее отображалась. Для динамических компонентов я удаляю кэш, как только контент меняется.
<?php
add_shortcode('latest-offers', function($atts) {
$key = 'sc_latest_offers_v1';
$html = wp_cache_get($key);
if ($html !== false) {
return $html;
}
$q = new WP_Query([
'post_type' => 'angebot',
'posts_per_page' => 5,
'no_found_rows' => true,
'fields' => 'all',
]);
ob_start();
if ($q->have_posts()) {
echo '<ul class="offers">';
while ($q->have_posts()) { $q->the_post();
echo '<li>' . esc_html(get_the_title()) . '</li>';
}
echo '</ul>';
wp_reset_postdata();
}
$html = ob_get_clean();
wp_cache_set($key, $html, '', 600);
return $html;
});
Быстро находить и устранять источники ошибок
Я активирую Отладка-мода и проверьте, правильно ли зарегистрирован шорткод. Часто белый экран или необработанный текст указывают на то, что функция не загружается или использует echo вместо return. Записи в журнале показывают неожиданные типы данных, неправильные атрибуты или отсутствующие эскейпы. В шаблонах я тестирую шаг за шагом: сначала статический текст, затем шорткод, затем параметры. Если вы хотите действовать систематически, воспользуйтесь руководством по Режим отладки WordPress.
Работайте с дочерней темой в режиме безопасности обновления
Я создаю свои собственные шорткоды в Детская тема если я не могу или не хочу ничего менять в родительской теме. Таким образом, настройки сохраняются при обновлении темы, и я могу контролировать последовательность загрузки. Важно: правильно зарегистрируйте дочернюю тему, держите functions.php в порядке и включайте только определенные файлы. Для структурированных проектов я отделяю шорткоды в /inc и документирую их с помощью встроенных комментариев. Компактное руководство можно найти на сайте Инструкции для дочерних тем.
Стилизация, семантика и доступность
Я забочусь о чистоте HTML и семантические теги, чтобы устройства чтения с экрана правильно распознавали содержимое. Я отображаю кнопки в виде тега с role="button", только если они действительно являются ссылками, в противном случае я выбираю настоящие кнопки. Я поддерживаю высокие цветовые контрасты и устанавливаю стили фокусировки, чтобы пользователи клавиатуры могли четко видеть, где они находятся. Я сокращаю количество встроенных стилей и переношу дизайн в файл CSS с понятными классами. Это позволяет сделать шорткоды гибкими и в то же время доступными.
Интеграция API и безопасная интеграция внешних данных
Я получаю внешние данные через wp_remote_get и кэшировать их, чтобы страница не зависала во время таймаутов API. Я проверяю ответы на коды состояния, контролируемо разбираю JSON и разрешаю только те поля, которые действительно необходимы. В случае сбоев я показываю неаккуратный резервный вывод или скрываю блок. Для пользовательского контента я удаляю опасные теги и тщательно проверяю ссылки. Благодаря этому шорткоды остаются стабильными даже при колебаниях внешних сервисов.
Загружайте активы только тогда, когда они используются
Я загружаю CSS/JS для шорткодов, только если они действительно появляются на странице. Это экономит запросы и сохраняет критический путь CSS небольшим. Я регистрирую стили и скрипты централизованно и подгружаю их в обратном вызове или специально, как только узнаю шорткод в контенте. Важно: никогда не пишите жесткий код в заголовке без раздумий, а работайте через API enqueue.
<?php // functions.php – Регистрация ресурсов add_action('wp_enqueue_scripts', function() { wp_register_style('my-shortcodes', get_template_directory_uri() . '/assets/shortcodes.css', [], '1.0');
wp_register_script('my-shortcodes', get_template_directory_uri() . '/assets/shortcodes.js', [], '1.0', true); });
// Загружать только при наличии в контенте add_action('wp', function() { if (is_singular() && has_shortcode(get_post_field('post_content', get_queried_object_id()), 'button')) { wp_enqueue_style('my-shortcodes');
wp_enqueue_script('my-shortcodes'); } }); // Альтернативно вызвать непосредственно в обратном вызове шорткода: function my_assets_example_shortcode($atts, $content = null) { wp_enqueue_style('my-shortcodes'); return '<div class="my-box">' . wp_kses_post($content) . '</div>';
}
add_shortcode('my-box', 'my_assets_example_shortcode');
Шорткоды против прямого вызова функций в шаблоне
Я делаю сознательное различие: для модулей с фиксированным шаблоном я предпочитаю вызывать функцию напрямую, а не разбирать шорткод. Это экономит накладные расходы, повышает читабельность и позволяет избежать неожиданных эффектов фильтрации. Шорткоды предназначены для редакционного контента; шаблоны выигрывают от ясных вызовов функций с понятными параметрами.
<?php
// Вместо:
echo do_shortcode('[greeting]');
// Лучше в шаблоне:
echo my_greeting_shortcode();
Вложенные шорткоды и форматирование
Я учитываю вложенные шорткоды и автоматическую вставку тегов p и br. Если шорткоды заключают в себе другое содержимое, я продолжаю отображать внутреннее содержимое с помощью do_shortcode, но разрешаю только разрешенные теги. Я удаляю неприглядные теги p вокруг шорткодов с помощью shortcode_unautop, если в противном случае разметка будет разорвана.
<?php function my_wrap_shortcode($atts, $content = null) { $inner = do_shortcode($content); // разрешить вложенные шорткоды return '<div class="wrap">' . wp_kses_post($inner) . '</div>';
}
add_shortcode('wrap', 'my_wrap_shortcode');
// Необязательная помощь при форматировании
add_filter('the_content', 'shortcode_unautop');
Интернационализация и локализация
Я поддерживаю языковые возможности шорткодов: перевожу текстовые строки с помощью текстового домена темы и использую date_i18n для дат. Таким образом, модули работают в многоязычном окружении и остаются неизменными при переключении языков. Я локализую тексты по умолчанию непосредственно в обратных вызовах шорткодов и удаляю их в зависимости от контекста.
<?php
// Тема подготовлена к переводу
add_action('after_setup_theme', function() {
load_theme_textdomain('my-theme', get_template_directory() . '/languages');
});
// Локализованное приветствие
function my_greeting_shortcode() {
return esc_html__('Здравствуйте, добро пожаловать на мой сайт!', 'my-theme');
}
// Локализованный год
add_shortcode('current-year', function() {
return esc_html(date_i18n('Y'));
});
Признание кэша недействительным, варианты и ключи
Я планирую кэши таким образом, чтобы варианты были четко разделены, а содержимое быстро устаревало при внесении изменений. Такие атрибуты, как лимит или таксономия, включаются в ключ. При сохранении соответствующих типов постов я специально удаляю затронутые ключи. В системах с высоким трафиком я полагаюсь на бэкэнд постоянного кэша объектов и группирую ключи по признакам, чтобы можно было очищать их коллективно.
<?php
add_shortcode('latest-offers', function($atts) {
$atts = shortcode_atts(['limit' => 5], $atts, 'latest-offers');
$limit = max(1, (int) $atts['limit']);
$key = 'sc_latest_offers_v1_' . $limit;
if (($html = wp_cache_get($key, 'mytheme')) !== false) {
return $html;
}
$q = new WP_Query([
'post_type' => 'angebot',
'posts_per_page' => $limit,
'no_found_rows' => true,
]);
ob_start();
if ($q->have_posts()) {
echo '<ul class="offers">';
while ($q->have_posts()) { $q->the_post();
echo '<li>' . esc_html(get_the_title()) . '</li>';
}
echo '</ul>';
wp_reset_postdata();
}
$html = ob_get_clean();
wp_cache_set($key, $html, 'mytheme', 600);
return $html;
});
// Cache invalidieren, wenn Angebote geändert werden
add_action('save_post_angebot', function() {
foreach ([1,5,10] as $limit) {
wp_cache_delete('sc_latest_offers_v1_' . $limit, 'mytheme');
}
});
Усиление безопасности: sanitiser, разрешенные атрибуты и rel/target
Я расширяю шорткоды с помощью разумных, но безопасных опций. Для ссылок я ограничиваю target до _self/_blank и устанавливаю rel="noopener noreferrer" для новых вкладок. Я проверяю цвета с помощью sanitize_hex_color. К контенту я отношусь контекстно-чувствительно, для закрытого контента я выбираю wp_kses_post или более строгий allowlist.
<?php
add_shortcode('button', function($atts, $content = null) {
$atts = shortcode_atts([
'text' => '',
'url' => '#',
'color' => '#2d89ef',
'target' => '_self'
], $atts, 'button');
$text = $atts['text'] !== '' ? $atts['text'] : ($content ?: esc_html__('Нажмите сейчас', 'my-theme'));
$text = esc_html($text);
$url = esc_url($atts['url']);
$color = sanitise_hex_color($atts['color']) ?: '#2d89ef';
$target = in_array($atts['target'], ['_self','_blank'], true) ? $atts['target'] : '_self';
$rel = $target === '_blank' ? 'noopener noreferrer' : '';
$style = 'background:' . $colour . ';padding:8px 18px;color:#fff;border-radius:4px;text-decoration:none';
return '<a class="sc-button" href="/ru/' . $url . '/" style="' . esc_attr($style) . '" target="' . esc_attr($target) . '" rel="' . esc_attr($rel) . '">' . $text . '</a>';
});
Контексты редактора, виджета и ленты
Я учитываю контекст, в котором работает шорткод. Я явно разрешаю шорткоды в классических текстовых виджетах и использую блок шорткодов в редакторе блочных виджетов. В лентах или в поиске я деактивирую особо сложные шорткоды и возвращаю пустые. Кроме того, я загружаю активы на отдельных страницах, только если шорткод появляется в контенте.
<?php
// Классические виджеты: активируйте шорткоды
add_filter('widget_text', 'do_shortcode');
// Избегайте дорогостоящего вывода в фидах
add_shortcode('latest-offers-feed-safe', function($atts) {
if (is_feed()) {
return '';
}
// ... обычный вывод
});
Износ, переход на блоки и совместимость
Я планирую будущее своих шорткодов: Когда тег заменяется, я перенаправляю его на новый на некоторое время и сообщаю об этом в журнале изменений. Если вы полагаетесь на редактор блоков, вы можете зарегистрировать блоки на стороне сервера с помощью render_callback и использовать ту же функцию PHP внутри шорткода. Таким образом, оба пути будут спокойно сосуществовать до истечения срока действия шорткода.
'', 'url' => '#'], $atts, 'old-button');
$text = $map['text'] ?: $content;
return do_shortcode('[button text="" . esc_attr($text) . '" url="" . esc_url($map['url']) . '"]');
});
// Позже: удаляем полностью
// remove_shortcode('old-button');
Испытания и обеспечение качества
Я проверяю критические шорткоды с помощью модульных тестов, чтобы рефакторинг не принес никаких сюрпризов. В тестах я проверяю, что обязательные атрибуты проверены, значения по умолчанию установлены и вывод корректно экранирован. Для вывода HTML я выбираю надежные утверждения (contains вместо exact match), чтобы небольшие изменения форматирования не привели к поломке всех тестов. Я также проверяю такие крайние случаи, как пустое содержимое, недопустимые цвета и очень длинные тексты.
assertStringContainsString('Hi', $out);
$this->assertStringContainsString('href="#"', $out);
}
public function test_button_blocked_invalid_color() {
$out = do_shortcode('[button color="javascript:alert(1)"]');
$this->assertStringNotContainsString('javascript:', $out);
}
}
В заключение: мой компактный практический обзор
Я четко регистрирую шорткоды, поставляю их в безопасном режиме и храню их в Кэширование быстро. Для редакционного использования я документирую примеры и обеспечиваю согласованные параметры, чтобы все могли использовать их с уверенностью. Модули, связанные с макетом, помещаются в тему, а функции, связанные с контентом, - в плагин, чтобы сайт оставался гибким в долгосрочной перспективе. С дочерней темой, журналами отладки и чистой семантикой разработка и обслуживание остаются спокойными. В результате получается тема wordpress с шорткодами, которая надежно отображается, проста в обслуживании и дает контент-командам реальную свободу.


