...

Использование шорткодов WordPress в вашей собственной теме - технология, примеры и лучшие практики

Я покажу вам, как я регистрирую шорткоды прямо в теме, доставляю их в безопасное место и отображаю в нужных местах - вот как я создаю тема 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' =&gt; [], 'em' =&gt; [], 'a' =&gt; ['href' =&gt; []]);
    $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' =&gt; '#',
        'color' =&gt; '#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.

&lt;?php // functions.php – Регистрация ресурсов add_action(&#039;wp_enqueue_scripts&#039;, function() { wp_register_style(&#039;my-shortcodes&#039;, get_template_directory_uri() . &#039;/assets/shortcodes.css&#039;, [], &#039;1.0&#039;);
    wp_register_script(&#039;my-shortcodes&#039;, get_template_directory_uri() . &#039;/assets/shortcodes.js&#039;, [], &#039;1.0&#039;, true); });

// Загружать только при наличии в контенте add_action(&#039;wp&#039;, function() { if (is_singular() &amp;&amp; has_shortcode(get_post_field(&#039;post_content&#039;, get_queried_object_id()), &#039;button&#039;)) { wp_enqueue_style(&#039;my-shortcodes&#039;);
        wp_enqueue_script(&#039;my-shortcodes&#039;); } }); // Альтернативно вызвать непосредственно в обратном вызове шорткода: function my_assets_example_shortcode($atts, $content = null) { wp_enqueue_style(&#039;my-shortcodes&#039;); return &#039;<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, если в противном случае разметка будет разорвана.

&lt;?php function my_wrap_shortcode($atts, $content = null) { $inner = do_shortcode($content); // разрешить вложенные шорткоды return &#039;<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' =&gt; '#',
        'color' =&gt; '#2d89ef',
        'target' =&gt; '_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 с шорткодами, которая надежно отображается, проста в обслуживании и дает контент-командам реальную свободу.

Текущие статьи

Современные серверные стойки в центре обработки данных с визуализацией потоков данных
Веб-сервер Plesk

Почему HTTP-запросы могут блокироваться, даже если доступно достаточно ресурсов

Узнайте, почему HTTP-запросы блокируются, даже если ресурсы все еще свободны. В статье объясняются причины, поведение веб-сервера и ограничения параллелизма, а также показаны стратегии оптимизации.

Общие сведения

Контрольный список для вашего сайта: 5 вещей, которые нужно сделать перед установкой WordPress

Многие потенциальные владельцы сайтов с энтузиазмом берутся за установку WordPress, но позже понимают, что пропустили важную подготовительную работу. Результат: разочарование,

Сервер в центре обработки данных с визуализацией загрузки процессора благодаря сжатию данных
Веб-сервер Plesk

Степень сжатия и загрузка процессора: как Gzip и Brotli влияют на производительность хостинга

Узнайте, как различные уровни сжатия влияют на загрузку процессора и как можно оптимизировать производительность хостинга с помощью целенаправленной настройки gzip и Brotli.