Back

Einen Custom Post Type in WordPress erstellen

Einen Custom Post Type in WordPress erstellen

WordPress wird standardmäßig mit Beiträgen und Seiten ausgeliefert, doch diese beiden Inhaltstypen reichen nicht weit, wenn ein Kunde ein Immobilienverzeichnis, eine Mitarbeiterliste oder ein Rezeptarchiv benötigt. Hier kommt ein WordPress Custom Post Type ins Spiel — eine vollwertige Inhaltsstruktur, die sich nahtlos in das bestehende Datenmodell von WordPress einfügt, ohne die Standardeinstellungen zu umgehen.

Wichtigste Erkenntnisse

  • Ein Custom Post Type (CPT) erweitert die gemeinsam genutzte wp_posts-Tabelle, anstatt eine separate zu erstellen, und bietet sofort Admin-Oberflächen, REST-API-Endpunkte und Template-Routing.
  • Registrieren Sie CPTs immer in einem Plugin, nicht in einem Theme, damit Inhalte unabhängig von Theme-Wechseln zugänglich bleiben.
  • Die Einstellung show_in_rest auf true ist erforderlich für die Unterstützung des Block-Editors und die Bereitstellung über die REST-API.
  • Rewrite-Regeln sollten nur bei Plugin-Aktivierung geleert werden — niemals bei jedem Seitenaufruf.

Was ist ein Custom Post Type?

Ein Custom Post Type (CPT) ist ein benannter Inhaltstyp, den Sie bei WordPress registrieren. Trotz des Namens handelt es sich nicht um eine separate Datenbanktabelle. Alle Post Types — eingebaute und benutzerdefinierte — teilen sich die wp_posts-Tabelle und werden durch die Spalte post_type unterschieden. Das ist ein wichtiges mentales Modell: Sie erweitern eine bestehende Struktur, anstatt eine parallele zu erstellen.

Zu den Standard-Post-Types gehören post, page, attachment, revision und nav_menu_item. Wenn Sie einen CPT wie property oder recipe registrieren, behandelt WordPress ihn mit derselben Konsistenz: Admin-Oberflächen, REST-API-Endpunkte, URL-Routing und Template-Hierarchie funktionieren alle auf die gleiche Weise.

Custom Post Types ≠ Custom Fields. Ein CPT definiert den Typ des Inhalts. Custom Fields (hinzugefügt über ACF oder die Metadata-API) speichern zusätzliche Daten, die an diesen Inhalt angehängt sind. Dies sind separate Anliegen.

Registrierung eines Custom Post Type mit register_post_type()

Der kanonische Weg, einen WordPress Custom Post Type zu erstellen, ist die Funktion register_post_type(), die am init-Hook aufgerufen wird.

Hier ist ein sauberes, funktionierendes Beispiel:

add_action( 'init', 'register_property_post_type' );

function register_property_post_type() {
    $labels = [
        'name'               => 'Properties',
        'singular_name'      => 'Property',
        'add_new_item'       => 'Add New Property',
        'edit_item'          => 'Edit Property',
        'not_found'          => 'No properties found.',
    ];

    $args = [
        'labels'       => $labels,
        'public'       => true,
        'has_archive'  => true,
        'supports'     => [ 'title', 'editor', 'thumbnail', 'excerpt' ],
        'rewrite'      => [ 'slug' => 'properties' ],
        'show_in_rest' => true,
    ];

    register_post_type( 'property', $args );
}

Wichtige Argumente erklärt

  • public — Macht den CPT im Admin-Bereich und im Frontend sichtbar. Setzen Sie dies auf false für rein interne Typen.
  • labels — Steuert alle UI-Texte im Admin-Bereich. Es lohnt sich, diese ordentlich auszufüllen, damit Redakteure nicht verwirrt werden.
  • supports — Deklariert, welche Editor-Funktionen auf dem Bearbeitungsbildschirm erscheinen. Häufige Werte: title, editor, thumbnail, excerpt, custom-fields.
  • has_archive — Aktiviert eine Archivseite unter /properties/. WordPress sucht nach einem passenden archive-property.php-Template (oder fällt auf archive.php zurück).
  • rewrite — Legt den URL-Slug fest. Einzelne Beiträge erscheinen unter /properties/post-name/.
  • show_in_restSetzen Sie dies auf true. Dies stellt den CPT über die WordPress REST API bereit und ist erforderlich, damit der Block-Editor korrekt mit Ihrem Post Type funktioniert. Ohne diese Einstellung fällt der Editor auf die klassische Oberfläche zurück.

Plugin vs. Theme: Wo sollte der Code leben?

Dies ist ein häufiger Punkt der Verwirrung. Registrieren Sie Ihren Custom Post Type in einem Plugin, nicht in einem Theme.

Wenn Ihre CPT-Registrierung in der functions.php liegt und der Kunde das Theme wechselt, werden alle Inhalte dieses Typs unzugänglich — nicht gelöscht, aber unsichtbar. Ein dediziertes Plugin (selbst ein einfaches Ein-Datei-Plugin) hält den CPT unabhängig von Theme-Wechseln aktiv.

Leeren Sie Rewrite-Regeln nicht bei jeder Anfrage. Rufen Sie flush_rewrite_rules() nur einmal auf — bei Plugin-Aktivierung über register_activation_hook(). Das Leeren bei jedem init ist ein Performance-Problem.

Template-Hierarchie für Custom Post Types

WordPress sucht nach Templates in dieser Reihenfolge für einen einzelnen CPT-Eintrag:

  1. single-{post-type}.php (z.B. single-property.php)
  2. single.php
  3. singular.php
  4. index.php

Für Archive folgt es: archive-{post-type}.phparchive.phpindex.php.

Fazit

Mit register_post_type(), korrekt am init-Hook eingehängt, aktiviertem show_in_rest und der Registrierung in einem Plugin haben Sie eine solide, portable Grundlage. Von hier aus können Sie Custom Taxonomies, Meta-Felder über ACF oder die Metadata-API und benutzerdefinierte Admin-Spalten hinzufügen — ohne etwas anzufassen, das bei WordPress- oder Theme-Updates kaputt gehen würde.

FAQs

Der Inhalt bleibt in der wp_posts-Tabelle und wird nicht gelöscht. WordPress erkennt diesen Post Type jedoch nicht mehr, sodass die Beiträge im Admin-Bereich und im Frontend unsichtbar werden. Die Reaktivierung des Plugins stellt den Zugriff sofort wieder her. Deshalb sollte die CPT-Registrierung immer in einem dedizierten Plugin und nicht in einem Theme erfolgen.

Ja. Sie können register_post_type() mehrmals innerhalb desselben init-Callbacks aufrufen oder separate Callbacks verwenden, die am init-Hook eingehängt sind. Es gibt keine Begrenzung für die Anzahl der Custom Post Types, die ein einzelnes Plugin registrieren kann, obwohl jeder einen eindeutigen Post-Type-Slug haben muss, der nicht länger als 20 Zeichen ist.

Dies bedeutet fast immer, dass die Rewrite-Regeln geleert werden müssen. Besuchen Sie Einstellungen und dann Permalinks im WordPress-Admin und klicken Sie auf Änderungen speichern. Das löst ein Rewrite-Flush aus. Rufen Sie für Plugins flush_rewrite_rules() innerhalb von register_activation_hook() auf, damit es automatisch bei der Aktivierung ausgeführt wird. Leeren Sie niemals bei jedem Seitenaufruf.

Nicht unbedingt, aber es wird dennoch empfohlen. Das Setzen von show_in_rest auf true stellt Ihren Post Type über die WordPress REST API bereit, was für Headless-Setups, externe Integrationen und zukünftige Kompatibilität nützlich ist. Wenn Sie jemals zum Block-Editor wechseln, wird er bereits korrekt funktionieren.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay