Jak tworzyć własne CPT (Custom Post Type)

dowiedz się
Spis treści

Własny typ treści (Custom Post Type) to fundament elastycznego modelowania danych w WordPress. Dzięki niemu porządkujesz zawartość w logiczne byty (np. Filmy, Kursy, Produkty), z własnymi polami, widokami i uprawnieniami. Poniższa instrukcja prowadzi od planowania po wdrożenie i optymalizację: od projektowania schematu treści, przez rejestrację i integrację z edytorem blokowym, aż po szablony, filtry w panelu i SEO. Po jej przejściu zbudujesz stabilne, skalowalne i czytelne CPT.

Planowanie i modelowanie treści przed stworzeniem CPT

Kiedy CPT, a kiedy taksonomia lub pola

Zanim utworzysz nowy typ treści, odpowiedz na pytanie: czy rzeczywiście potrzebujesz osobnego bytu? CPT sprawdza się, gdy:

  • Treść ma własny cykl życia: lista, edycja, archiwum, single, uprawnienia.
  • Chcesz mieć niezależne permalinki i strukturę URL (np. /filmy/… zamiast /blog/… ).
  • Wymagasz specyficznych szablonów: single-{typ}.php i archive-{typ}.php.
  • Panel powinien mieć osobne menu i filtry, a autorzy odrębne prawa.

Gdy potrzebujesz jedynie atrybutu klasyfikującego (np. gatunki, kategorie, tagi), postaw na taksonomie. Gdy chcesz przechowywać drobne dane dodatkowe (np. rok premiery), wystarczą pola niestandardowe lub ACF. Przesadne mnożenie CPT komplikuje nawigację i wydajność – modeluj oszczędnie, ale konsekwentnie.

Definiowanie pól i relacji

Spisz komplet informacji, jakie ma zawierać wpis nowego typu: np. Tytuł, Streszczenie, Reżyser, Obsada, Czas trwania, Okładka, Data premiery, Link do trailera. Zdecyduj:

  • które pola są tekstowe, liczbowe, logiczne, daty (wpływa to na walidację),
  • czy potrzebujesz relacji między typami (np. Film ↔ Reżyser jako osobny CPT),
  • jakie filtry w panelu przyspieszą pracę redakcji (gatunek, rok, status),
  • jakie elementy mają być wyeksponowane w listingu kolumn (miniatura, data, ocena).

Dobrze zaprojektowana struktura danych oszczędza późniejszego refaktoringu i migracji.

Nazewnictwo i slug

Slug CPT jest częścią adresu URL i identyfikatorem w kodzie. Wybierz:

  • machine name (np. film, course, event) – małe litery, bez spacji, bez polskich znaków,
  • slug w adresach (może się różnić: np. cpt „film”, slug „filmy”),
  • liczbę pojedynczą i mnogą do etykiet (Film/Filmy),
  • konsekwencję z istniejącą strukturą (np. /kursy/, /lekcje/).

Zmiana slugu w późniejszym etapie wymaga przekierowań i odświeżania reguł przepisywania, więc zaplanuj go raz a dobrze.

Hierarchiczność i archiwum

Zdecyduj, czy CPT jest hierarchiczny (jak strony) czy płaski (jak wpisy). Hierarchiczny CPT dostaje rodzic–potomek i „Atrybuty strony” w edycji. Włącz lub wyłącz archiwum (has_archive). Archive-{typ}.php ułatwia listowanie i paginację. Jeżeli tworzysz katalog lub repozytorium treści, archiwum bywa kluczowe dla UX i SEO.

Publiczność, prywatność i dostęp

Parametr „public” wpływa na widoczność w REST, zapytaniach, panelu i wyszukiwarkach. Potrzebne są decyzje:

  • public vs w pełni prywatne (np. wewnętrzne dokumenty),
  • exclude_from_search – czy ma trafiać do wyników wyszukiwania,
  • publicly_queryable – czy adresy single/archiwum działają publicznie,
  • show_in_nav_menus i show_ui – widoczność w menu i panelu.

Precyzja tych ustawień zmniejsza ryzyko wycieków treści i błędów uprawnień.

Rejestracja CPT krok po kroku

Gdzie umieścić kod: wtyczka vs functions.php

Unikaj lock-in w motywie. Rejestrację CPT najlepiej umieścić we własnej wtyczce (np. „site-core” lub „content-model”), aby przy zmianie motywu struktura treści pozostała. Minimalny szkielet:

  • folder wp-content/plugins/twoj-cpt/
  • plik twoj-cpt.php z nagłówkiem wtyczki
  • pliki inc/ dla porządku: cpt-film.php, tax-gatunek.php itd.

Włącz wtyczkę w panelu i kontroluj wersjonowanie przez Git.

Hook init i podstawy rejestracji

Rejestracji dokonujesz na akcji init. Najczęstsze pola konfiguracji:

  • label i labels – pełny zestaw etykiet w języku redakcji,
  • public, show_ui, show_in_menu, show_in_nav_menus,
  • show_in_rest – wymóg dla Gutenberg i REST API,
  • has_archive – true lub własny slug archiwum,
  • rewrite – slug, with_front, feeds, pages,
  • supports – np. title, editor, thumbnail, excerpt, revisions, custom-fields, page-attributes, author, comments,
  • menu_position, menu_icon (np. dashicons-video-alt2),
  • capability_type, map_meta_cap lub pełna tablica capabilities,
  • taxonomies – lista powiązanych taksonomii,
  • query_var – nazwa zmiennej w URL i WP_Query.

Dla zachowania kompatybilności edytora blokowego ustaw show_in_rest => true.

Etykiety (labels) z tłumaczeniami

Przygotuj kompletny zestaw etykiet w liczbie pojedynczej i mnogiej, uwzględniając odmianę przypadków po polsku. Przykłady:

  • name: Filmy, singular_name: Film,
  • add_new: Dodaj nowy, add_new_item: Dodaj nowy film,
  • edit_item: Edytuj film, new_item: Nowy film, view_item: Zobacz film,
  • search_items: Szukaj filmów, not_found: Nie znaleziono,
  • menu_name: Filmy.

Zadbaj o i18n (domain) – jeżeli tworzysz wtyczkę, używaj funkcji tłumaczeń z własną domeną tekstową.

Wsparcia (supports) i integracje edycyjne

Dobierz supports do potrzeb:

  • title i editor – typowe treści,
  • thumbnail – miniatury wymagają add_theme_support(’post-thumbnails’),
  • excerpt – krótkie zajawki do listingów,
  • revisions – historia zmian,
  • custom-fields – klasyczny metabox pól (dla bloków rekomendowane są metadane z rejestrem),
  • page-attributes – kolejność, hierarchia,
  • author, comments – jeśli dotyczą tego bytu.

Dodatkowo w argumentach CPT możesz ustawić 'template’ i 'template_lock’, aby wymusić domyślny układ bloków dla redakcji.

Parametry rewrite i archiwum

Rewrite pozwala kontrolować adresy:

  • slug – np. „filmy”,
  • with_front – dziedziczenie prefiksu kategorii (zwykle false),
  • feeds, pages – czy generować kanały RSS i paginację,
  • has_archive – włącz archiwum i określ jego slug (np. „kinoteka”).

Po dodaniu lub zmianie rewrite konieczne jest jednorazowe odświeżenie reguł (flush_rewrite_rules) – zrób to przy aktywacji wtyczki, nie przy każdym żądaniu.

Uprawnienia i mapowanie capabilities

Jeśli CPT ma własne role i prawa, nie ograniczaj się do capability_type => 'post’. Skonfiguruj:

  • capability_type => array(’film’, 'filmy’) dla liczby pojedynczej i mnogiej,
  • map_meta_cap => true,
  • capabilities – własna tablica: edit_film, read_film, delete_film, edit_films, edit_others_films, publish_films, read_private_films itd.,
  • add_role i add_cap – przypisz prawa redaktorom lub nowym rolom.

To pozwala stworzyć precyzyjny model bezpieczeństwa, szczególnie w zespołach.

Przykładowa rejestracja – opis kroków

Załóż typ „film” z archiwum „/filmy/”, ikoną „dashicons-video-alt2”, wsparciem dla tytułu, edytora, miniatury i zajawki, publiczny, widoczny w REST, z paginacją i slugiem „filmy”. W panelu umieść go pod Postami, nadaj własne etykiety i zintegruj z taksonomią „gatunek”. Zadbaj o flush reguł przy aktywacji i o tłumaczenia etykiet.

Taksonomie, pola i integracja z edytorem oraz API

Rejestracja taksonomii powiązanych

Taksonomie porządkują zawartość CPT. Zarejestruj „gatunek” (hierarchiczny, jak kategorie) i „tagi-filmu” (niehierarchiczny, jak tagi). Kluczowe parametry:

  • hierarchical – true/false,
  • show_in_rest – dla obsługi w edytorze blokowym,
  • rewrite – slug (np. „gatunek”),
  • meta_box_cb – domyślny metabox lub własny,
  • labels – pełne etykiety jak dla CPT.

Pamiętaj, by przypisać taksonomie do typów treści w argumencie „object_type” lub w samym CPT (pole „taxonomies”).

Pola niestandardowe: natywne, register_post_meta i ACF

Masz trzy główne drogi:

  • Natywne „custom-fields” – szybkie, lecz mało przyjazne i bez walidacji.
  • register_post_meta – rejestr metadanych z typami, sanitacją i show_in_rest; pozwala ujawnić metadane w REST API, sterować dostępem i edycją z bloków.
  • ACF – wizualny kreator pól, warunki wyświetlania, walidacja, grupy i elastyczne layouty; integruje się z blokami (ACF Blocks) i edytorem.

Dla długofalowych projektów polecane jest register_post_meta lub ACF, by utrzymać porządek i przewidywalność danych.

Edytor blokowy, pola w panelu i UX redakcji

Doskonałe UX redakcji to:

  • Własne kolumny w listingu (manage_edit-{cpt}_columns i manage_{cpt}_posts_custom_column) dla kluczowych metadanych.
  • Filtry nad tabelą (restrict_manage_posts), np. według gatunku i roku.
  • Domyślny szablon bloków (argument 'template’ w CPT), aby ujednolicić strukturę wpisów.
  • Wskazówki w edytorze (filter 'enter_title_here’), by podpowiedzieć format tytułu.
  • Walidacja i sanitacja pól, podpowiedzi placeholder, opisy i instrukcje.

Włącz show_in_rest, aby zasoby były w pełni edytowalne w bloku.

Publiczne API: REST i GraphQL

Przy show_in_rest => true, WordPress automatycznie dodaje endpointy /wp-json/wp/v2/{cpt}. Dodatkowe ustawienia:

  • rest_base – niestandardowa baza endpointów (np. „movies”).
  • rest_namespace – alternatywna przestrzeń nazw (np. „my/v1”) w nowszych wersjach WP.
  • rest_controller_class – jeżeli potrzebujesz niestandardowej logiki kontrolera.

Rejestruj metadane (register_post_meta) z show_in_rest => true i typem (string, number, boolean), by były dostępne w API. Jeśli używasz WPGraphQL, włącz 'show_in_graphql’ w CPT i taksonomiach lub skonfiguruj pola w schemacie.

Tłumaczenia i wielojęzyczność

Jeżeli wdrażasz Polylang/WPML:

  • Oznacz CPT jako translatable i zdefiniuj czy taksonomie mają wspólne czy oddzielne termy per język.
  • Sprawdź kompatybilność z URL: /pl/filmy/, /en/movies/ (osobne slug-i per język).
  • Utrzymuj spójność pól między wersjami językowymi i buduj logiczne fallbacki.

Zadbaj o spójne etykiety i eksport plików .po/.mo dla wtyczek z i18n.

Szablony motywu, wyświetlanie i zapytania

Hierarchia szablonów i podstawowe pliki

WordPress ma czytelną hierarchię dla CPT:

  • single-{cpt}.php – widok pojedynczego wpisu (np. single-film.php),
  • archive-{cpt}.php – archiwum typu (np. archive-film.php),
  • taxonomy-{tax}.php – lista dla taksonomii (np. taxonomy-gatunek.php),
  • single.php i archive.php – fallback, gdy brak plików specyficznych.

Dla spójności UI przygotuj dedykowane pliki i komponenty pętli. Zadbaj o stan pustej listy, komunikaty i paginację.

Zapytania do bazy: WP_Query i pre_get_posts

Aby pobierać wpisy CPT, konfiguruj WP_Query przez argument 'post_type’ => 'film’. Popularne wzorce:

  • Meta query (meta_query) dla filtrowania po roku, ocenie, czasie trwania.
  • Tax query (tax_query) dla gatunku, tagów, wielu warunków (relation AND/OR).
  • Order i orderby (np. meta_value_num) – ustaw odpowiednie indeksy w bazie.
  • pre_get_posts – zmień domyślne zapytania archiwów, aby dodać filtry i sortowania.

Stosuj lazy-loading obrazów i cache obiektów, aby ograniczyć koszty renderowania listingów.

Permalinki i reguły przepisywania

Po rejestracji CPT wejdź w Ustawienia → Bezpośrednie odnośniki i zapisz, aby przepisać reguły. W kodzie wykonuj flush_rewrite_rules() tylko:

  • po aktywacji/dezaktywacji wtyczki,
  • po istotnej zmianie slugów lub has_archive.

Unikaj flush na każdej stronie – to kosztowne. Jeśli masz 404 dla pojedynczych wpisów, problem zwykle rozwiązuje odświeżenie permalinków. Konflikty slugów z istniejącymi stronami i kategoriami rozwiąż zmianą sluga lub priorytetu reguł.

Paginacja, sortowanie i filtry na froncie

Zadbaj o UX list:

  • Paginacja oparta o paged i max_num_pages,
  • Sortowanie po metadanych (np. dacie premiery, ocenie),
  • Filtry GET (gatunek, rok), budując bezpieczne i pamiętliwe linki,
  • Kanoniczne URL-e i rel=”next/prev” dla robotów.

Przy złożonych filtrach rozważ dedykowany kontroler (stronę szukajki) i cache wyników, aby nie przeciążać zapytań do postmeta.

Elementy SEO i dostępności

Konsekwentne SEO dla CPT:

  • Unikalne tytuły i metaopisy (współpraca z wtyczką SEO),
  • Przyjazne breadcrumbsy z nazwą typu treści,
  • Mapa witryny – upewnij się, że archiwa CPT i taksonomii są włączone,
  • Dane strukturalne (JSON-LD) – dopasowane do rodzaju treści (np. Movie, Course),
  • Dostępność: kontrasty, semantyka, focus, alt dla miniatur.

Ustal noindex dla zbędnych listingów (np. przefiltrowanych kombinacji, które duplikują treść), aby uniknąć kanibalizacji słów kluczowych.

Zarządzanie w panelu, bezpieczeństwo i wydajność

Kolumny, sortowanie i szybka edycja

Ulepsz widoki listowe redakcji:

  • Dodaj kolumny (np. Rok, Gatunek, Ocena) i umożliw sortowanie (manage_edit-{cpt}_sortable_columns + meta_query w pre_get_posts).
  • Włącz szybkie akcje (Quick Edit) oraz zintegrowane pola do masowej edycji.
  • Przy dużej liczbie wpisów dodaj wyszukiwanie po metadanych (dedykowane pole nad tabelą).

Te zmiany radykalnie skracają czas operacji redakcyjnych.

Zasady bezpieczeństwa

Bezpieczny CPT to:

  • Nonces w metaboxach, sprawdzenie current_user_can przed zapisem,
  • Sanitacja (sanitize_text_field, esc_url_raw) i walidacja typów,
  • Escapowanie przy wyjściu (esc_html, esc_attr, wp_kses),
  • map_meta_cap i granularne capabilities dla ról,
  • Ograniczenie uprawnień REST (permission_callback, register_post_meta auth_callback),
  • Ukrycie w panelu pól lub akcji dla nieuprawnionych użytkowników.

Regularne przeglądy kodu i testy ról minimalizują ryzyko regresji.

Wydajność i skalowanie

Przy rosnącej liczbie wpisów:

  • Indeksuj postmeta (np. composite index dla często używanych kluczy),
  • Ogranicz meta_query OR – rozważ dedykowane tabele, gdy zapytań jest bardzo dużo,
  • Cache obiektów i transients dla list, filtrów i liczników,
  • Lazy-load, preloading, optymalizacja miniatur,
  • Stronicowanie REST i selektywne pola (?_fields=) dla lżejszych odpowiedzi.

Migracja do dedykowanych tabel (np. przy użyciu narzędzi typu wpdb lub wtyczek ORM) ma sens przy krytycznych potrzebach raportowania i filtrowania.

Rewizje, workflow i statusy niestandardowe

Dla złożonej redakcji rozważ:

  • Własne statusy (register_post_status), np. „Do recenzji”, „Zarchiwizowany”.
  • Integrację z narzędziami workflow (np. powiadomienia e-mail/Slack na zmianę statusu).
  • Rozszerzoną moderację komentarzy, jeśli CPT ją wspiera.

Wyraźnie zdefiniowane etapy publikacji ograniczają pomyłki i poprawiają jakość treści.

Eksploatacja, migracje, testy i narzędzia

WP-CLI i scaffolding

Automatyzuj:

  • Generowanie szkieletu typu: wp scaffold post-type film –theme lub –plugin,
  • Rejestrację taksonomii: wp scaffold taxonomy gatunek –post_types=film,
  • Masowe operacje: wp post list –post_type=film, wp export –post_type=film.

Skrypty CLI przyspieszają wdrożenia i ograniczają błędy ręczne.

Migracja treści do nowego CPT

Jeżeli zaczynałeś od wpisów (post) i potrzebujesz przenieść dane:

  • Użyj WP-CLI (wp post update ID –post_type=film) lub krótkiego skryptu z wp_update_post.
  • Zmapuj pola: przenieś metadane do register_post_meta/ACF, skonwertuj kategorie do nowej taksonomii.
  • Wykonaj przekierowania 301 ze starych URL na nowe (np. poprzez rankujące wpisy blogowe → /filmy/).
  • Zaktualizuj sitemapę i przetestuj indeksację.

Testuj migrację na stagingu i wykonaj kopię bazy przed wdrożeniem.

Testy, wersjonowanie i CI/CD

Stosuj:

  • Testy jednostkowe (WP_UnitTestCase) dla rejestracji i filtrów,
  • Testy akceptacyjne (np. Playwright/Cypress) dla panelu i frontu,
  • Kontrolę wersji wtyczki z kodem CPT, changelog i semver,
  • Deployment z automatycznym flush rewirte przy aktywacji i warm-up cache.

Weryfikuj także regresje wydajnościowe (profilery, Query Monitor).

Kompatybilność multisite i środowisk

W sieci multisite:

  • Rejestruj CPT globalnie, ale pamiętaj, że wpisy należą do blog_id;
  • Jeśli agregujesz treści między witrynami, używaj switch_to_blog z rozwagą i cache’uj wyniki;
  • Aktualizacje reguł przepisywania i ustawień wykonuj per witrynę.

Dopilnuj, aby migracje i skrypty CLI iterowały po wszystkich blogach sieci.

Typowe problemy i ich diagnoza

Najczęstsze pułapki:

  • 404 po rejestracji – brak flush rewrite (wejdź w Ustawienia → Bezpośrednie odnośniki i zapisz).
  • Brak edytora blokowego – show_in_rest wyłączone lub brak supports 'editor’.
  • Brak miniatur – brak add_theme_support(’post-thumbnails’) lub rola bez uprawnień do uploadu.
  • 403 przy edycji – nieprawidłowe map_meta_cap lub rola bez właściwych caps.
  • Duplikacja zawartości – nakładające się archiwa i taksonomie, brak rel=canonical.
  • Wydajność – ciężkie meta_query bez indeksów; rozważ przebudowę modelu lub dedykowane tabele.
  • Konflikt slugów – strona lub kategoria o tym samym adresie co CPT; zmień jeden ze slugów.

W diagnozie pomaga Query Monitor, logi REST, testy ról i tymczasowe wyłączenie wtyczek konfliktujących.

Checklist wdrożeniowy dla solidnego CPT

Przed publikacją:

  • Przegląd schematu danych: pola, taksonomie, relacje, walidacja.
  • Rejestracja CPT z poprawnymi labels, supports, rewrite, has_archive, show_in_rest, capabilities.
  • Taksonomie z show_in_rest i przyjaznym slugiem.
  • Metadane przez register_post_meta lub ACF, z sanitacją i typami.
  • Szablony: single-{cpt}.php, archive-{cpt}.php, taxonomy-{tax}.php; paginacja, breadcrumbs.
  • Filtrowanie i kolumny w panelu; sortowalność po kluczowych metadanych.
  • Uprawnienia ról; testy edycji, publikacji i kasowania.
  • Flush rewrite przy aktywacji; test 404 i kanonicznych URL-i.
  • REST API i integracje z frontem (SPA, mobilne), ograniczenie pól (?_fields=).
  • Wydajność: cache, lazy-load, indeksy, monitoring.
  • Kopia zapasowa i plan rollbacku.

Z tak przygotowanym zestawem wdrożenie jest przewidywalne i skalowalne.

Praktyczne wzorce dla wielu projektów

Sprawdzone praktyki:

  • Jedna wtyczka „core” na projekt: centralizuje CPT, taksonomie, rejestr metadanych, role, statusy.
  • Nazwy w języku angielskim dla kluczy (slugów) – mniejsza szansa konfliktów, łatwiej w API.
  • Spójny system nazewnictwa metadanych (np. _film_release_year, _film_rating).
  • Domyślne obrazy zastępcze i walidacja wymagalności (required) w polach.
  • Wersjonowanie zmian w strukturze (migracje DB, konwersje danych, redirecty).
  • Dokumentacja dla redakcji: co oznaczają pola, jak publikować, jak tagować.

Takie wzorce upraszczają współpracę i przyspieszają onboarding kolejnych osób.

Rozszerzenia: endpointy, sitemap, integracje

Gdy projekt rośnie:

  • Dodaj własne endpointy REST z rejestracją tras i permission_callback.
  • Eksporty/Importy: wp export –post_type=film, dedykowane feedy RSS/JSON.
  • Integracja z wyszukiwarką (ElasticPress), jeśli filtrów jest dużo i meta_query rosną.
  • Panel raportowy: zagregowane widoki, wykresy (wp_list_table, strony narzędziowe).
  • Webhooki na publikację/aktualizację – integracje z CRM/marketing automation.

Planuj API kontraktowo i opisuj schematy pól, by uniknąć niekompatybilnych zmian.

Mały słownik pojęć użytecznych przy CPT

Dla szybkiej orientacji:

  • CPTCustom Post Type, własny typ treści w WP.
  • register_post_type – funkcja rejestrująca typ treści.
  • WP_Query – klasa do zapytań o wpisy i ich listowanie.
  • REST API – interfejs /wp-json/wp/v2/… do pracy z danymi.
  • Gutenberg – edytor blokowy WordPress.
  • ACF – Advanced Custom Fields, wtyczka do pól.
  • capabilities – granularne uprawnienia do operacji na treści.
  • taksonomie – kategorie/tagi porządkujące treści.
  • SEO – optymalizacja widoczności w wyszukiwarkach.
  • permalinki – struktura stałych adresów URL w serwisie.

Praktyczne opanowanie tych pojęć sprawia, że projektowanie i wdrażanie CPT staje się przewidywalne oraz łatwe do utrzymania.

< Powrót

Zapisz się do newslettera


Zadzwoń Napisz