Jak stworzyć własne shortcode

dowiedz się

Stworzenie własnego, lekkiego mechanizmu wstawiania powtarzalnych elementów do treści to prosty sposób na porządek i szybkość pracy. Krótki kod – tzw. shortcode – pozwala zamienić zawiłe fragmenty HTML, zapytań lub logiki na jeden prosty znacznik. Dzięki temu autorzy skupiają się na treści, a programista na logice i jakości. Poniżej znajdziesz praktyczną instrukcję: od planu, przez implementację i stylowanie, po testy, utrzymanie i publikację w formie mini‑wtyczki.

Plan i fundamenty: co chcesz osiągnąć i jak działa shortcode

Co to jest i dlaczego warto

Shortcode to niewielki znacznik w treści, np. [cennik id=12], który podczas renderowania strony jest zamieniany na wynik funkcji w PHP. W praktyce możesz ukryć pod nim karty FAQ, tabele, formularze, listy ofert, a nawet zaawansowane komponenty oparte na API. Dobrze zaprojektowany shortcode ogranicza duplikację kodu, upraszcza edycję oraz minimalizuje ryzyko błędów. Daje też spójny wygląd w całym serwisie niezależnie od autora wpisu.

Jak działa mechanizm w WordPress

Silnik WordPress wczytuje treść wpisu i skanuje ją pod kątem wzorców [nazwa …]…[/nazwa] lub [nazwa …]. Gdy znajdzie dopasowanie, uruchamia przypisaną do nazwy funkcję w PHP. Funkcja dostaje atrybuty (tablicę klucz-wartość) oraz ewentualną zawartość wewnętrzną (content). Zwrócony wynik (jako string) zastępuje oryginalny znacznik. Dzięki temu możesz budować komponenty oparte na danych dynamicznych, uwzględniające atrybuty i kontekst.

Kiedy użyć, a kiedy nie

  • Użyj, gdy treść ma powtarzalny wzór i wymaga parametrów (np. lista wpisów z wybranej kategorii, sekcja CTA, blok kontaktu).
  • Unikaj, gdy potrzebujesz rozbudowanego układu redakcyjnego – wówczas lepszy może być blok edytora Gutenberg lub dedykowany szablon.
  • Jeśli kluczowa jest kontrola nad dostępem do danych, rozważ też komponenty serwerowe z kontrolą ról i uprawnień.

Minimalny plan przed rozpoczęciem

  • Określ atrybuty, ich typy i wartości domyślne (np. id:int, layout:string, limit:int).
  • Zdecyduj, czy shortcode ma zawierać wewnętrzną treść (np. [box]Tekst[/box]).
  • Wybierz miejsce implementacji: functions.php motywu potomnego czy osobna wtyczka.
  • Przygotuj strategię na bezpieczeństwo (sanityzacja danych wejściowych, escapowanie wyjścia) oraz wydajność (cache, lazy loading).

Pierwszy shortcode krok po kroku

Gdzie dodać kod: motyw czy wtyczka

Na start możesz wstawić kod do functions.php w motywie potomnym. To najszybsza ścieżka, ale pamiętaj, że zmiana motywu usunie funkcję. Trwalszym rozwiązaniem jest mała wtyczka: dzięki temu logika nie jest związana z wyglądem i przetrwa aktualizacje motywu.

Rejestracja i podstawowa funkcja

Najprostszy przykład – shortcode zwracający aktualny rok:

function mysite_year_shortcode( $atts, $content = null ) {
  return date(’Y’);
}
add_shortcode( 'rok’, 'mysite_year_shortcode’ );

Użycie w treści: [rok]

Obsługa atrybuty i wartość domyślna

Przykład z atrybutami i domyślnymi wartościami (shortcode_atts):

function mysite_box_shortcode( $atts, $content = null ) {
  $atts = shortcode_atts([
    'title’ => 'Informacja’,
    'type’ => 'info’,
  ], $atts, 'box’);

  $title = sanitize_text_field( $atts[’title’] );
  $type = sanitize_key( $atts[’type’] );

  $html = '<div class=”box box-’ . esc_attr($type) . '”>’;
  $html .= '<strong class=”box-title”>’ . esc_html($title) . '</strong>’;
  $html .= '<div class=”box-content”>’ . wp_kses_post( do_shortcode( $content ) ) . '</div>’;
  $html .= '</div>’;
  return $html;
}
add_shortcode( 'box’, 'mysite_box_shortcode’ );

Użycie: [box title=Uwaga type=warning]To jest ostrzeżenie[/box]

Zwracanie vs. echo i organizacja szablonów

Funkcja callback powinna zwracać, a nie wypisywać (echo) treść. Jeśli korzystasz z rozbudowanego HTML, rozważ buforowanie wyjścia:

function mysite_card_shortcode( $atts ) {
  $atts = shortcode_atts([’title’ => ”], $atts, 'card’);
  ob_start(); ?>
  <article class=”card”>
   <h4><?php echo esc_html( $atts[’title’] ); ?></h4>
   <div class=”card-body”>Treść karty</div>
  </article>
  <?php return ob_get_clean();
}
add_shortcode(’card’,’mysite_card_shortcode’);

Możesz też renderować osobny szablon PHP (np. template‑part), przekazując do niego zmienne; pamiętaj o izolacji przestrzeni nazw i braku efektów ubocznych.

Praca z treścią i danymi: od prostych do zaawansowanych przykładów

Treść zagnieżdżona, filtry i przetwarzanie

Shortcode może mieć treść wewnętrzną: [quote]Lorem ipsum[/quote]. Aby zadziałały inne shortcody w środku, używaj do_shortcode($content). W przypadku cytatów i tekstu sformatowanego stosuj wp_kses_post, aby dopuścić bezpieczne znaczniki, a resztę odfiltrować. Jeśli chcesz dodać filtr pozwalający innym wtyczkom modyfikować wynik, użyj apply_filters na finalnym HTML.

Zapytania i pętle WP_Query

Przykład listy wpisów z kategorii z parametrami:

function mysite_posts_shortcode( $atts ) {
  $atts = shortcode_atts([
    'cat’ => ”,
    'limit’ => 5,
  ], $atts, 'listapostow’);

  $cat = sanitize_text_field( $atts[’cat’] );
  $limit = absint( $atts[’limit’] );

  $q = new WP_Query([
    'category_name’ => $cat,
    'posts_per_page’ => $limit,
    'no_found_rows’ => true,
  ]);

  if ( ! $q->have_posts() ) {
    return '<p>Brak wpisów.</p>’;
  }

  ob_start(); ?>
  <ul class=”post-list”>
   <?php while ( $q->have_posts() ) : $q->the_post(); ?>
    <li><a href=”<?php the_permalink(); ?>”><?php the_title(); ?></a></li>
   <?php endwhile; ?>
  </ul>
  <?php wp_reset_postdata();
  return ob_get_clean();
}
add_shortcode(’listapostow’,’mysite_posts_shortcode’);

Wydajność pętli poprawisz parametrem no_found_rows, a jeśli nie wyświetlasz miniaturek, wyłącz także pobieranie pól niepotrzebnych (fields => 'ids’).

Wczytywanie i rejestrowanie zasobów (CSS/JS)

Shortcode bywa zależny od stylów i skryptów. Zarejestruj je i ładuj tylko, gdy shortcode występuje. W pliku wtyczki lub motywu zrób:

function mysite_assets() {
  wp_register_style(’mysite-box’,’/path/to/box.css’,[], '1.0′);
  wp_register_script(’mysite-box’,’/path/to/box.js’,[’jquery’],’1.0′, true);
}
add_action(’wp_enqueue_scripts’,’mysite_assets’);

A w funkcji shortcode, przed zwróceniem wyniku:

wp_enqueue_style(’mysite-box’);
wp_enqueue_script(’mysite-box’);

Dzięki temu unikasz globalnego wstrzykiwania zasobów na każdej podstronie.

Tłumaczenia, formatowanie i dostępność

Wszystkie teksty użytkownika przepuść przez funkcje tłumaczeń i escapowania: esc_html__( 'Tytuł’, 'textdomain’ ). Dodaj atrybuty ARIA, odpowiedni kontrast i semantyczny HTML. Jeśli shortcode tworzy elementy interaktywne, zadbaj o focus i obsługę klawiatury. To ważne nie tylko z punktu widzenia UX, ale i SEO.

Jakość, sanityzacja, bezpieczeństwo i wydajność

Walidacja wejścia i escapowanie wyjścia

  • Dla tekstu: sanitize_text_field, esc_html.
  • Dla adresów: esc_url, wp_validate_redirect (jeśli link przekierowuje).
  • Dla liczb: absint, floatval + walidacja zakresu.
  • Dla kluczy CSS/klas: sanitize_key, esc_attr.
  • Dla HTML od użytkownika: wp_kses lub wp_kses_post z dozwolonym zestawem tagów.

Wszystkie dane w atrybutach shortcodu traktuj jak nieufne. Nie wykonuj eval, nie parsuj JSON bez walidacji i nie twórz zapytań SQL z wstrzykniętymi wartościami. Jeśli łączysz się z API, obsłuż błędy i time‑outy.

Uprawnienia i ograniczenia

Choć shortcode działa zwykle na froncie, rozważ sprawdzenie ról, jeśli wyświetlasz dane wrażliwe. Przykład: ukryj adres e‑mail lub sekcję administracyjną, gdy ! is_user_logged_in() lub użytkownik nie ma potrzebnej roli (current_user_can). Pamiętaj, że atrybuty w treści mogą pochodzić od edytorów o różnym poziomie zaufania.

Buforowanie, transients i minimalizacja zapytań

Jeśli shortcode wykonuje kosztowne operacje (zapytania, API), keszuj wynik na krótki okres:

function mysite_cached_box( $atts ) {
  $key = 'mys_box_’ . md5( maybe_serialize( $atts ) );
  $cached = get_transient( $key );
  if ( false !== $cached ) return $cached;
  $html = '<div class=”box”>…wynik…</div>’;
  set_transient( $key, $html, MINUTE_IN_SECONDS * 10 );
  return $html;
}

Pamiętaj o czyszczeniu cache (np. na hookach save_post lub edycji ustawień) i o tym, by klucz zależał od atrybutów oraz istotnych warunków (język, użytkownik, parametry adresu).

Debugowanie i testy

  • Włącz WP_DEBUG_LOG i loguj etapy działania krótkich kodów (error_log).
  • Przygotuj testowe treści z różnymi wariantami atrybutów i treścią zagnieżdżoną.
  • Sprawdź działanie w edytorze wizualnym i na froncie, także w podglądzie AMP jeśli używasz.
  • Stosuj testy jednostkowe dla funkcji pomocniczych (parsowanie atrybutów, walidacja danych).

Od snippets do wtyczki: struktura, publikacja i utrzymanie

Minimalna struktura wtyczki

Utwórz katalog w wp-content/plugins, np. mysite-shortcodes, a w nim plik mysite-shortcodes.php:

<?php
/*
Plugin Name: MySite Shortcodes
Description: Zestaw krótkich kodów dla serwisu.
Version: 1.0.0
Author: Ty
Text Domain: mysite-sc
*/

if ( ! defined( 'ABSPATH’ ) ) exit;

function mysite_sc_register() {
  add_shortcode( 'box’, 'mysite_box_shortcode’ );
  add_shortcode( 'rok’, 'mysite_year_shortcode’ );
}
add_action( 'init’, 'mysite_sc_register’ );

function mysite_year_shortcode( $atts ){ return date(’Y’); }
function mysite_box_shortcode( $atts, $content = null ){ /* … jak wyżej … */ }

Taka forma ułatwia migrację między motywami i pozwala wersjonować kod niezależnie.

Konwencje nazewnicze i unikanie kolizji

  • Prefiksuj wszystko (np. mysite_ lub org_). Nazwy shortcodów również: mysite_box zamiast box, jeśli przewidujesz konflikt.
  • Trzymaj logikę w funkcjach prywatnych dla wtyczki; eksportuj tylko to, co konieczne.
  • Jeśli krótkie kody mają podobne atrybuty, zbuduj wspólną warstwę walidacji i helpery.

Stylowanie i motywowalność

Dodaj klasy CSS, które można łatwo nadpisać w motywie. Jeśli to możliwe, wprowadź atrybut layout (np. compact, full) i generuj semantyczny HTML. Udostępnij filtr, który pozwoli nadpisać szablon (apply_filters(’mysite_box_template’, $html, $atts)). Dzięki temu inni deweloperzy dopasują komponent do swoich potrzeb.

Dokumentacja i komunikacja z redakcją

  • Przygotuj krótką ściągę: nazwy, atrybuty, przykłady użycia, zrzuty ekranów.
  • W treści pomocy dołącz warianty najczęstszych błędów oraz oczekiwane typy danych.
  • Ustal proces zgłaszania poprawek i wersjonuj zmiany (CHANGELOG). W repozytorium trzymaj przykładowe treści do szybkich testów.

Współpraca z blokami i rozwój w przyszłości

Most między shortcode a blokiem

W środowiskach z edytorem blokowym wielu autorów treści woli wizualne komponenty. Możesz zarejestrować blok, który pod spodem wywoła shortcode w PHP (render_callback). To otwiera drogę do edytora, a zachowuje istniejącą logikę. W JS przygotuj atrybuty bloku, a w PHP w render_callback skonstruuj parametry i wywołaj do_shortcode.

Migracja do natywnych bloków

Jeśli planujesz porzucić shortcode, dodaj wtyczce mechanizm migracji: przy zapisie treści zamieniaj [box …] na odpowiadający mu blok z identycznymi atrybutami. Dzięki temu zachowasz wsteczną kompatybilność, a nowe treści będą tworzone blokowo.

Kompatybilność i aktualizacje

  • Testuj po aktualizacjach rdzenia, PHP i wtyczek, które mogą ingerować w filtr the_content.
  • Dodaj automatyczne testy smoke (czy shortcode istnieje, czy funkcja zwraca string, czy nie ma błędów PHP).
  • Wprowadzaj zmiany nieniszczące: jeśli zmieniasz API atrybutów, zachowaj aliasy lub ostrzegaj w logach.

Przykładowe wzorce, które warto naśladować

  • Shortcode karta: atrybuty title, icon, link; semantyczny article i aria‑label.
  • Shortcode lista wpisów: cache transients, no_found_rows, lazy‑rendering obrazków.
  • Shortcode CTA: parametry tekstu i koloru, oddzielone style w CSS i warianty layoutu.
  • Shortcode FAQ: możliwość zagnieżdżania i automatyczne generowanie schema.org FAQPage.

Checklist: od pierwszej linijki do wdrożenia

Projekt i implementacja

  • Zdefiniowane atrybuty, wartości domyślne, typy i walidacja.
  • Wydzielone funkcje pomocnicze (np. budowa zapytań, czyszczenie danych).
  • Brak efektów ubocznych w callbacku; zawsze zwracasz string.

Jakość i testy

  • Sanityzacja wejścia i escapowanie wyjścia w każdym miejscu.
  • Scenariusze brzegowe: puste wyniki, błędne atrybuty, brak połączenia z API.
  • Logika pod testy jednostkowe, a CSS i JS ładowane warunkowo.

Wydajność i cache

  • Ogranicz liczbę zapytań do bazy (prefetch, select fields=ids, no_found_rows).
  • Użyj transients z krótkim TTL i czyść je po zmianach danych.
  • Minimalizuj rozmiar HTML i unikaj kosztownych operacji w pętli.

Utrzymanie i rozwój

  • Wersjonowanie, changelog, testy kompatybilności.
  • Dokumentacja dla redakcji z przykładami użycia i FAQ.
  • Plan przejścia do bloku, jeśli wymaga tego kierunek rozwoju edycji treści.

Na koniec szybki przykład łączący kilka dobrych praktyk – shortcode wyświetlający link do ostatniego wpisu z wybranej kategorii z prostym cache i walidacją:

function mysite_lastpost_link( $atts ) {
  $atts = shortcode_atts([’cat’ => ”], $atts, 'lastlink’);
  $cat = sanitize_text_field( $atts[’cat’] );
  $key = 'mys_last_’ . md5( $cat );
  if ( $cached = get_transient( $key ) ) return $cached;

  $q = new WP_Query([
    'category_name’ => $cat,
    'posts_per_page’ => 1,
    'no_found_rows’ => true,
    'fields’ => 'ids’,
  ]);
  if ( ! $q->have_posts() ) return '<span>Brak wpisów</span>’;
  $id = $q->posts[0];
  $html = '<a class=”last-link” href=”’ . esc_url( get_permalink($id) ) . '”>’ . esc_html( get_the_title($id) ) . '</a>’;
  set_transient( $key, $html, MINUTE_IN_SECONDS * 5 );
  return $html;
}
add_shortcode(’lastlink’,’mysite_lastpost_link’);

Tak przygotowany komponent łączy jasne API atrybutów, walidację, kontrolę prezentacji oraz rozsądną warstwę cache – dobry punkt wyjścia dla dalszych modyfikacji i rozwoju Twojej biblioteki krótkich kodów.

< Powrót

Zapisz się do newslettera


Zadzwoń Napisz