Czym są Custom Post Types?
WordPress domyślnie obsługuje kilka wbudowanych typów treści: wpisy (posts), strony (pages), multimedia i komentarze. Custom Post Types (CPT) to mechanizm, który pozwala ci zarejestrować własne typy treści — np. Portfolio, Recenzje, FAQ czy Nieruchomości — z własnym panelem administracyjnym, polami i zachowaniem.
CPT nie są wtyczką — to natywna funkcja WordPressa dostępna od wersji 3.0. Rejestrujesz
je przez wywołanie funkcji register_post_type() w pliku
functions.php lub w dedykowanej wtyczce.
Kiedy warto używać CPT? Jeśli treść ma własną strukturę, własne pola i powinna wyświetlać się w oddzielnej sekcji panelu — CPT to właściwe narzędzie. Nie nadużywaj wpisów dla wszystkiego.
Rejestracja własnego typu wpisu
Funkcję rejestrującą wpinamy w hook init, żeby WordPress ją
wykonał we właściwym momencie ładowania. Poniżej przykład rejestracji CPT
o nazwie Portfolio:
<?php
/**
* Rejestracja Custom Post Type: Portfolio.
*/
function moj_rejestruj_portfolio(): void {
$labels = [
'name' => 'Portfolio',
'singular_name' => 'Projekt',
'menu_name' => 'Portfolio',
'add_new' => 'Dodaj projekt',
'add_new_item' => 'Dodaj nowy projekt',
'edit_item' => 'Edytuj projekt',
'new_item' => 'Nowy projekt',
'view_item' => 'Zobacz projekt',
'search_items' => 'Szukaj projektów',
'not_found' => 'Nie znaleziono projektów',
'not_found_in_trash' => 'Brak projektów w koszu',
];
$args = [
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => [ 'slug' => 'portfolio' ],
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'menu_position' => 5,
'menu_icon' => 'dashicons-portfolio',
'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt' ],
'show_in_rest' => true, // aktywuje blok Gutenberg
];
register_post_type( 'portfolio', $args );
}
add_action( 'init', 'moj_rejestruj_portfolio' );
Po zarejestrowaniu nowego CPT pamiętaj o odświeżeniu permalinków: Ustawienia → Bezpośrednie odnośniki → Zapisz zmiany. Bez tego adresy URL nowego typu będą zwracały błąd 404.
Własne taksonomie
Do grupowania wpisów CPT możesz stworzyć własne taksonomie — hierarchiczne (jak kategorie) lub płaskie (jak tagi). Poniżej rejestracja taksonomii Technologia dla CPT Portfolio:
<?php
/**
* Rejestracja taksonomii: Technologia.
*/
function moj_rejestruj_technologie(): void {
$labels = [
'name' => 'Technologie',
'singular_name' => 'Technologia',
'search_items' => 'Szukaj technologii',
'all_items' => 'Wszystkie technologie',
'edit_item' => 'Edytuj technologię',
'update_item' => 'Zaktualizuj technologię',
'add_new_item' => 'Dodaj nową technologię',
'new_item_name' => 'Nazwa nowej technologii',
'menu_name' => 'Technologie',
];
register_taxonomy(
'technologia', // nazwa taksonomii
[ 'portfolio' ], // powiązane CPT
[
'hierarchical' => true, // true = kategorie, false = tagi
'labels' => $labels,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => [ 'slug' => 'technologia' ],
'show_in_rest' => true,
]
);
}
add_action( 'init', 'moj_rejestruj_technologie' );
Wyświetlanie CPT w szablonie
Domyślna pętla WordPressa (The Loop) nie obejmuje wpisów CPT.
Aby pobrać własne typy, używasz klasy WP_Query z jawnym
podaniem nazwy CPT:
<?php
$portfolio_query = new WP_Query([
'post_type' => 'portfolio',
'posts_per_page' => 6,
'orderby' => 'date',
'order' => 'DESC',
'tax_query' => [
[
'taxonomy' => 'technologia',
'field' => 'slug',
'terms' => 'php',
],
],
]);
if ( $portfolio_query->have_posts() ) :
while ( $portfolio_query->have_posts() ) :
$portfolio_query->the_post();
?>
<article class="portfolio-card">
<h2><?php the_title(); ?></h2>
<?php the_post_thumbnail( 'medium' ); ?>
<?php the_excerpt(); ?>
<a href="<?php the_permalink(); ?>">Zobacz projekt</a>
</article>
<?php
endwhile;
wp_reset_postdata(); // !!! zawsze resetuj po własnym WP_Query
endif;
Wywołanie wp_reset_postdata() po własnym WP_Query
jest obowiązkowe. Bez niego globalna zmienna $post
pozostaje przestawiona na ostatni wpis z Twojego zapytania, co może powodować
nieprzewidywalne błędy w dalszej części szablonu.
Pliki szablonów CPT
WordPress automatycznie szuka plików szablonów dla CPT według hierarchii.
Dla CPT o nazwie portfolio:
single-portfolio.php— szablon pojedynczego projektuarchive-portfolio.php— szablon listy projektówtaxonomy-technologia.php— szablon listy wg taksonomii
Utwórz te pliki w katalogu motywu i WordPress automatycznie ich użyje
zamiast domyślnego single.php czy archive.php.
<?php
// single-portfolio.php — minimal example
get_header();
while ( have_posts() ) :
the_post();
?>
<main class="portfolio-single">
<h1><?php the_title(); ?></h1>
<?php
$terms = get_the_terms( get_the_ID(), 'technologia' );
if ( $terms ) {
foreach ( $terms as $term ) {
echo '<span class="tag">' . esc_html( $term->name ) . '</span>';
}
}
?>
<?php the_content(); ?>
</main>
<?php
endwhile;
get_footer();
Wskazówka organizacyjna: Zamiast wrzucać rejestrację CPT
bezpośrednio do functions.php, utwórz plik
includes/post-types.php i dołącz go przez
require_once get_template_directory() . '/includes/post-types.php'.
Utrzymasz porządek przy rosnącym projekcie.
Podsumowanie
Custom Post Types to jeden z najważniejszych mechanizmów WordPressa. Kilkadziesiąt linii kodu daje Ci dedykowany section w panelu, własne URL-e, taksonomie, szablony i pełną integrację z blokami Gutenberga oraz REST API.
Klucz do sukcesu to dobre etykiety (użytkownik widzi je codziennie w panelu),
przemyślana struktura supports i zawsze — odświeżone permalinki
po pierwszej rejestracji.