Skip to content
⚡ Jak dodać swój shortcode w WordPress: przykłady i kod

⚡ Jak dodać swój shortcode w WordPress: przykłady i kod

Potrzebują Państwo wyświetlić datę ostatniej aktualizacji wpisu w stopce każdego artykułu. Albo wstawić formularz subskrypcji dokładnie w środku tekstu, bez edytora kodu i kombinowania z szablonami. W WordPressie służą do tego shortkody.

Shortkod to krótki znacznik w nawiasach kwadratowych: [myshortcode]. WordPress znajduje go w treści i podmienia na wynik funkcji PHP. Standardowych shortkodów, takich jak [gallery] czy [embed], używają Państwo stale, nawet się nad tym nie zastanawiając. Ale własny shortkod to dźwignia: raz napisana logika, a redaktor wstawia ją gdziekolwiek trzema kliknięciami.

W 10 minut stworzą Państwo pierwszy działający shortkod: od pustej funkcji po znacznik z atrybutami i zagnieżdżoną treścią. Kod jest prawdziwy, uruchamia się na każdym współczesnym WordPressie, przetestowany na witrynie testowej.

💡 Szybki przegląd:

  • Funkcja add_shortcode: co przyjmuje i jak jest zbudowana od środka
  • Podstawowy shortkod [current_year], bieżący rok w tekście
  • Shortkod z atrybutami [cta text="Скачать"], niestandardowy przycisk
  • Shortkod z zagnieżdżoną treścią [notice]Текст[/notice], stylizowany blok
  • Podłączanie przez wtyczkę lub functions.php: plusy i minusy każdego sposobu
  • Typowe błędy: echo zamiast return, konflikt nazw, pusty atrybut w PHP 8+

Co potrafi add_shortcode i jak działa

Funkcja add_shortcode to jedyny standardowy sposób zarejestrowania nowego shortkodu w WordPressie. Przyjmuje dwa parametry:

  • $tag (string), nazwa shortkodu, którą będą Państwo wpisywać w nawiasach kwadratowych. Tylko litery, cyfry i podkreślenia. Spacje i znaki specjalne & / < > [ ] = są zabronione, WordPress po cichu odmówi rejestracji takiego znacznika.
  • $callback (callable), nazwa funkcji PHP, która uruchomi się po wykryciu shortkodu. To właśnie ona generuje ten HTML, który zobaczy odwiedzający.

Kod źródłowy funkcji to pięć linii logiki i dwa zabezpieczenia przed błędami (pełny listing na 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}

Kluczowy moment: $shortcode_tags to globalna tablica. WordPress przechowuje w niej wszystkie zarejestrowane shortkody. Podczas renderowania treści rdzeń przechodzi przez tę tablicę i dla każdego znalezionego znacznika wywołuje powiązaną funkcję. Wynikają z tego dwie konsekwencje:

  • *Rejestruj na haku init.* Jeśli podepną Państwo add_shortcode bezpośrednio w pliku wtyczki, może ona zadziałać przed pełną inicjalizacją WordPressa. Prawidłowy sposób to opakowanie w hak:
1add_action( 'init', 'my_register_shortcodes' );
2
3function my_register_shortcodes() {
4 add_shortcode( 'mytag', 'my_shortcode_callback' );
5}
  • Prefiks jest obowiązkowy. Globalna tablica jest jedna dla wszystkich wtyczek i motywu. Nazwą Państwo shortkod [button], a Państwa [button] po cichu nadpisze taki sam shortkod z wtyczki formularzy. Prefiks w rodzaju myplugin_ lub unikalnego skrótu rozwiązuje problem. W poniższych przykładach używam prefiksu mysite_, w rzeczywistym projekcie proszę go zastąpić własnym.

Krok 1: prosty shortkod bez parametrów

Najkrótsza droga do działającego shortkodu to trzy linie w functions.php motywu potomnego (lub we wtyczce Code Snippets, tak jest bezpieczniej, nie zginie przy aktualizacji motywu).

Proszę dodać ten kod i zapisać:

1add_shortcode( 'mysite_current_year', 'mysite_display_current_year' );
2
3function mysite_display_current_year() {
4 return date( 'Y' );
5}

Teraz w dowolnym wpisie lub na stronie proszę wpisać [mysite_current_year]. Na froncie zamiast shortkodu wyświetli się bieżący rok: „2026".

Co tu się dzieje. Funkcja mysite_display_current_year nie przyjmuje argumentów, wywołuje funkcję PHP date('Y') i zwraca ciąg czterech cyfr. WordPress podstawia ten ciąg dokładnie w to miejsce, w którym stał shortkod. Żadnej magii.

Gdzie to zastosować w praktyce: rok w stopce (© [mysite_current_year]), wiek projektu w tekście („działamy od [mysite_current_year] roku"), automatyczna aktualizacja dat na stronach prawnych.

Krok 2: shortcode z atrybutami

Shortcode bez parametrów jest przydatny, ale prawdziwa elastyczność zaczyna się od atrybutów. Klasyczny przykład: przycisk z konfigurowalnym tekstem i linkiem:

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}

W edytorze należy użyć go tak:

1[mysite_cta text="Download plugin" url="https://example.com/myplugin/"]

Funkcja shortcode_atts robi trzy rzeczy jednocześnie: scala atrybuty użytkownika z wartościami domyślnymi, filtruje tylko znane klucze i normalizuje pusty ciąg do tablicy (bez niej, przy wywołaniu [mysite_cta] bez atrybutów w PHP 8+, wystąpi TypeError, ponieważ pierwszy parametr funkcji callback otrzyma pusty ciąg, a nie tablicę).

*Dlaczego esc_url i esc_html.* Shortcode wstawia edytor, dziś jest to Pan/Pani, a jutro content manager bez dostępu do kodu. Eskapowanie na wyjściu zabezpiecza przed przypadkowym XSS, gdyby do atrybutu text trafił nawias lub znacznik.

Krok 3: shortcode z zagnieżdżoną treścią

Niektóre shortkody opakowują fragment tekstu: [mysite_notice]Важное сообщение[/mysite_notice]. Zagnieżdżona treść trafia do callbacka jako drugi parametr, $content. Typowy scenariusz: stylizowany blok z ostrzeżeniem:

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}

Proszę zwrócić uwagę na do_shortcode( $content ). Jeśli wewnątrz Pana/Pani shortcodu edytor wstawił inny shortcode (na przykład [mysite_current_year]), to opakowanie uruchomi również i jego. Bez do_shortcode zagnieżdżone shortkody wyświetlą się jako tekst w nawiasach kwadratowych, surowe [mysite_current_year] zamiast „2026".

CSS dla bloku, minimalny, na początek:

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}

Proszę dodać style w style.css motywu potomnego lub przez Wygląd → Dostosuj → Dodatkowy CSS.

Krok 4: shortcode wewnątrz wtyczki (podejście obiektowe)

Gdy shortkodów jest więcej niż trzy, functions.php zamienia się w śmietnik. Czas wynieść logikę do osobnej wtyczki, a najlepiej do klasy. Oto szkielet miniwtyczki z jednym shortkodem:

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();

Proszę umieścić ten plik w wp-content/plugins/mysite-shortcodes/mysite-shortcodes.php i aktywować wtyczkę w panelu administracyjnym. Shortcode [mysite_email address="hello@example.com"] wyświetli link zabezpieczony przed spam-botami, funkcja antispambot koduje znaki adresu e-mail na encje HTML.

Dlaczego klasa, a nie zestaw funkcji. Przestrzeń nazw: trzy shortkody w klasie nie kolidują z zewnętrznymi funkcjami. Plus autoloading, plus czytelny kod, jeśli wtyczka rozrośnie się do kilkunastu shortkodów.

Testowanie shortcodu przed publikacją

Po dodaniu kodu proszę sprawdzić trzy scenariusze:

  • Shortcode bez atrybutów. Po prostu [mysite_cta], powinien wyrenderować się z wartościami domyślnymi (tekst „Learn more", link #).
  • Shortcode z atrybutami. Pełen zestaw parametrów, wszystkie wartości zostały pobrane i wyświetlone poprawnie.
  • Błąd w atrybutach. Nieprawidłowy email w [mysite_email], funkcja po cichu zwraca pusty ciąg, zamiast zepsuć stronę.

Ważne: nigdy nie należy używać echo wewnątrz funkcji callback. Shortcode musi zwracać ciąg znaków przez return. Jeśli wyprowadzi się HTML przez echo, pojawi się on nie w miejscu shortcodu, ale na samej górze strony, ponieważ WordPress uruchamia renderowanie shortkodów przed wyprowadzeniem treści. Ta sama logika co w filtrach: funkcja oddaje wartość, a silnik sam decyduje, gdzie ją wstawić.

Drugi niuans: jeśli shortcode się nie wyświetla (widzą Państwo [mysite_cta] jako tekst, a nie przycisk), proszę sprawdzić, czy funkcja jest zarejestrowana na haku init, a nie bezpośrednio w ciele wtyczki. Bez init globalna tablica $shortcode_tags może nie być jeszcze gotowa na przyjęcie nowych znaczników.

Shortcode w motywie a we wtyczce: co wybrać

Kryterium

functions.php motywu

Osobna wtyczka

Szybkość startu

Szybciej, plik jest już załadowany

Nieco wolniej, osobny plik

Przenośność

Związany z motywem

Działa z każdym motywem

Przetrwanie podczas aktualizacji

Ginie podczas aktualizacji motywu

Żyje niezależnie

Wygoda edycji

Wygląd → Edytor plików motywu

Edytor wtyczek lub FTP

Dla ilu shortkodów

1-3

4+

Zasada: zaczynają Państwo od functions.php na stronie testowej, tworzą trzy shortkody, a następnie wynoszą je do wtyczki. Aktualizacja motywu za pół roku nie pogrzebie Pana/Pani logiki, a przeniesienie shortkodów na inny projekt zajmie minutę.

⁉️🤔 Często zadawane pytania

Jaka jest różnica między shortcode’em a blokiem Gutenberga?

Shortcode to tekstowy tag w nawiasach kwadratowych, który jest przetwarzany po stronie serwera. Blok to wizualny komponent edytora, komponent React z ustawieniami w panelu bocznym. Shortcode’y pojawiły się w WordPress 2.5 (2008), bloki, w 5.0 (2018). Dziś bloki są podstawowym sposobem wstawiania dynamicznej treści, ale shortcode’y pozostają aktualne: są prostsze w tworzeniu, nie wymagają znajomości JavaScript i działają w każdym edytorze, w tym w Classic Editor i konstruktorach stron.

Shortcode to tekstowy tag, który WordPress zastępuje wynikiem funkcji PHP podczas generowania strony. W przeciwieństwie do bloku Gutenberga, shortcode nie ma interfejsu wizualnego w edytorze: content manager wpisuje [myshortcode] jako tekst, a na froncie widzi gotowy HTML.

Czy można użyć shortcode’a wewnątrz innego shortcode’a?

Tak. Jeśli funkcja callback zewnętrznego shortcode’a opakowuje zagnieżdżoną treść w do_shortcode(), wewnętrzne shortcode’y zadziałają poprawnie: [notice][current_year][/notice] wyświetli stylizowany blok z bieżącym rokiem. Bez do_shortcode() zagnieżdżony shortcode pozostanie tekstem w nawiasach kwadratowych.

Zagnieżdżone shortcode’y są przetwarzane rekurencyjnie: WordPress przechodzi przez ciąg znaków kilka razy, aż nie pozostaną żadne nieprzetworzone tagi. Ale aby to zadziałało, zewnętrzny shortcode musi jawnie wywołać do_shortcode($content). W przeciwnym razie ciąg [current_year] pozostanie tekstem, zamiast zamienić się na „2026".

Dlaczego mój shortcode nie działa i wyświetla się jako tekst w nawiasach kwadratowych?

Trzy częste przyczyny. Pierwsza: add_shortcode zostało wywołane przed hookiem init, proszę przenieść rejestrację do wnętrza add_action('init', ...). Druga: literówka w nazwie tagu: [my_shortcode] w edytorze, a zarejestrowano myshortcode. Trzecia: funkcja callback używa echo zamiast return, przez co wynik trafia na początek strony, a w miejscu shortcode’a jest pusto.

Najczęściej winowajcą jest echo zamiast return w funkcji callback. WordPress wywołuje procedury obsługi shortcode’ów przed wyświetleniem głównej treści, więc wynik echo trafia do bufora wyjściowego wcześniej niż nagłówek strony. Proszę otworzyć kod źródłowy strony (Ctrl+U): jeśli widzi Pan/Pani HTML shortcode’a na samej górze, przed <html>, problem leży właśnie w tym.

Czy należy eskejpować dane wyjściowe shortcode’a?

Obowiązkowo. Shortcode przyjmuje atrybuty od redaktora, a zatem potencjalnie od dowolnego użytkownika z uprawnieniami autora lub redaktora. esc_html() dla tekstu, esc_url() dla linków, esc_attr() dla atrybutów HTML. Wyjątek stanowi sytuacja, gdy świadomie zwraca Pan/Pani znaczniki HTML (np. <div class="notice">). Ale nawet wtedy należy eskejpować atrybuty wewnątrz tych znaczników.

Tak, eskejpowanie jest obowiązkowe dla wszystkiego, co pochodzi z atrybutów shortcode’a lub danych wprowadzonych przez użytkownika. Nawet jeśli dziś shortcode’y wstawia tylko Pan/Pani, jutro dostęp do edytora może otrzymać content manager. esc_html() dla tekstu, esc_url() dla linków, esc_attr() dla atrybutów HTML chronią przed przypadkowym lub celowym atakiem XSS.

Ile shortcode’ów można zarejestrować na jednej stronie?

Nie ma technicznego limitu: $shortcode_tags to zwykła tablica PHP, więc o pamięć serwera oprze się Pan/Pani znacznie później niż o zdrowy rozsądek. W praktyce po 15-20 niestandardowych shortcode’ach warto się zastanowić: czy nie pora przenieść części z nich do bloków Gutenberga? Shortcode’y z unikalną logiką (zaciemnianie adresów e-mail, warunkowe wyświetlanie według roli) proszę zostawić. Shortcode’y służące wyłącznie do stylizacji tekstu ([highlight]) lepiej zastąpić stylem bloku lub klasą CSS.

Technicznie rzecz biorąc, można ich mieć dowolną liczbę, tablica $shortcode_tags nie ma sztucznego limitu. W praktyce ponad 20-25 shortcode’ów na jednej stronie świadczy o tym, że część logiki warto już przenieść do bloków. Każdy shortcode dodaje narzut na parsowanie treści: przed wyświetleniem WordPress przechodzi przez całą tablicę zarejestrowanych tagów i szuka dopasowań w tekście wpisu.

Czy warto pisać własne shortcode’y, czy wystarczą gotowe wtyczki?

Gotowa wtyczka pokrywa większość typowych zadań: formularze, Contact Form 7, tabele, TablePress, siatki, dowolny page builder. Własny shortcode jest potrzebny, gdy logika jest specyficzna dla Pana/Pani strony i nie ma gotowego rozwiązania: wyświetlenie pola niestandardowego dokładnie w tym miejscu strony, data następnego webinaru z bazy danych, spersonalizowane powitanie zależne od roli użytkownika.

Krótko mówiąc: do typowych funkcji proszę użyć wtyczki i nie programować. Do unikalnej logiki, add_shortcode + functions.php lub miniwtyczka. Kodu w każdym z powyższych przykładów jest mniej niż dziesięć linijek. Po opanowaniu tych trzech wzorców (prosty, z atrybutami, z zagnieżdżoną treścią) rozwiąże Pan/Pani zdecydowaną większość zadań, do których w ogóle pisze się niestandardowe shortcode’y.