- Plan i fundamenty: co chcesz osiągnąć i jak działa shortcode
- Co to jest i dlaczego warto
- Jak działa mechanizm w WordPress
- Kiedy użyć, a kiedy nie
- Minimalny plan przed rozpoczęciem
- Pierwszy shortcode krok po kroku
- Gdzie dodać kod: motyw czy wtyczka
- Rejestracja i podstawowa funkcja
- Obsługa atrybuty i wartość domyślna
- Zwracanie vs. echo i organizacja szablonów
- Praca z treścią i danymi: od prostych do zaawansowanych przykładów
- Treść zagnieżdżona, filtry i przetwarzanie
- Zapytania i pętle WP_Query
- Wczytywanie i rejestrowanie zasobów (CSS/JS)
- Tłumaczenia, formatowanie i dostępność
- Jakość, sanityzacja, bezpieczeństwo i wydajność
- Walidacja wejścia i escapowanie wyjścia
- Uprawnienia i ograniczenia
- Buforowanie, transients i minimalizacja zapytań
- Debugowanie i testy
- Od snippets do wtyczki: struktura, publikacja i utrzymanie
- Minimalna struktura wtyczki
- Konwencje nazewnicze i unikanie kolizji
- Stylowanie i motywowalność
- Dokumentacja i komunikacja z redakcją
- Współpraca z blokami i rozwój w przyszłości
- Most między shortcode a blokiem
- Migracja do natywnych bloków
- Kompatybilność i aktualizacje
- Przykładowe wzorce, które warto naśladować
- Checklist: od pierwszej linijki do wdrożenia
- Projekt i implementacja
- Jakość i testy
- Wydajność i cache
- Utrzymanie i rozwój
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.