Mit Custom Post Types (CPT) kannst du die verschiedensten Inhaltsformen und Funktionen deiner Website klar voneinander trennen und somit effizient verwalten.
In diesem Artikel lernst du, was ein CPT ist, und wie du einen Eigenen anlegst. Weiterführende Infos, mit denen du eine Metabox und eigene Templates für deinen Custom Post Type erstellen kannst, gibt’s obendrauf.
Robert Rosanke
Webentwickler
Inhaltsverzeichnis
Diesen Artikel in sozialen Netzwerken teilen:
Vorab-Exkurs: Was ist ein Post Type?
Einige von WordPress mitgelieferte Post Types sind:
- post (Beitrag)
- page (Seite)
- attachment (Uploads in die Mediathek)
Für jeden Post Type können individuelle Einstellungen hinzugefügt werden.
Für Beiträge sind beispielsweise eigene Templates und Archivseiten gängig, um die Ausgabe im Frontend zu steuern.
Doch auch die Bearbeitungsoberfläche im Backend kann beispielsweise durch Metaboxen individualisiert werden.
Und an dieser Stelle kommen Custom Post Types ins Spiel.
Was sind Custom Post Types?
Custom Post Types sind eigens erstellte Beitragstypen, mit denen eine WordPress Installation übersichtlich erweitert werden kann.
Du kannst zum Beispiel einen eigenen Post Type erstellen, die Bearbeitungsoberfläche um ein paar Metaboxen für zusätzliche Daten erweitern, ein eigenes Template bereitstellen und ihm einen individuellen Menüpunkt namens „Produkte“ geben.
Dadurch wird die Verwaltung der Websitesinhalte deutlich vereinfacht, weil die verschiedenen Themengebiete und Inhaltsformen im Backend visuell voneinander getrennt sind und einzelne Menüpunkte und angepasste Bearbeitungsoberflächen für die verschiedenen Inhalte der Seite erhalten.
Redakteure können sich dadurch super einfach zurechtfinden und die Inhalte effizient verwalten..
(Das oben beschrieben Beispiel könnte der erste Schritt für eine Produkt-Übersichtsseite, wie in einem Online Shop oder auf einer Affiliate-Seite, sein.)
Echte-Welt Beispiele für Custom Post Types:
- Formulare beliebter Kontaktformular-Plugins
- Produkte in diversen Affiliate Themes oder Shop-Erweiterungen
- Terminverwaltung für Künstler
- Portfolios für Dienstleister
- Immobilien-Listings in diversen Plugins und Themes
Einsatzgebiete und Grenzen
Das alles klingt auf den ersten Blick super.
Ist es auch.
Doch wie so oft, gibt es auch bei Custom Post Types irgendwann Grenzen.
Die sehe ich persönlich bei dynamischen Anwendungen, die kein Caching ermöglichen, und Daten aus vielen individuellen Metafeldern ziehen.
Denn dann wird ein Seitenaufruf alleine schon zahlreiche Datenbankabfragen zur Folge haben.
(Das ist an sich eher weniger ein Problem.)
Doch ohne Caching und mit einer hohen Zahl an gleichzeitigen Websitesbesuchern wird viel Rechenleistung benötigt, um den Content weitehrin „on the fly“ zusammenzustellen und geringe Ladezeiten bereitzustellen.
Da viele Menschen und Unternehmen aber genau beim Hosting sparen, kann das zu viel für einen leistungsschwachen Server sein und ziemlich auf die Performance drücken.
Mögliche Lösungsansätze:
- Fragment-Caching
- Für alle Metadaten eines Beitrags nur einen Datenbankeintrag anlegen und die Daten in einem einem JSON-(ähnlichen)-Format in einer eigenen Tabelle (engl) speichern
- Könnte bei starkem Gebrauch von Metafeldern die Datenbankabfragen beschleunigen.
- Bin mir aber nicht sicher, wie stark die Auswirkung davon in der Praxis wirklich wäre…
- Framework-Wahl überdenken – es gibt mehr als nur WordPress
Meine Meinung: Solange Caching möglich ist, ist alles in Butter. Für alles mit vielen Datenabfragen ohne Caching-Möglichkeit muss ein klarer Plan her, damit die Website auch mit steigendem Besucheraufkommen effizient funktionieren kann
Custom Post Type erstellen
Im folgenden ein Beispielcode zum registrieren eines Custom Post Types.
Ziel ist es Ferienwohnungen übersichtlich zu verwalten und jedem Objekt mit Metaboxen Eingabefelder für die Kerneigenschaften bereitzustellen.
Kerneigenschaften sind beispielsweise:
- Quadratmeter
- Preis
- Anzahl der Zimmer
Schritt 1: Funktion vorbereiten
Erstelle zuerst eine neue Funktion, die deinen Custom Post Type beinhaltet.
Über die init()
Hook wird die Funktion, und damit auch der Custom Post Type, später ins System integriert.
function wf_register_custom_post_type_apartment() {
}
add_action( 'init', 'wf_register_custom_post_type_apartment', 0 );
wf_register_custom_post_type_apartment
ist der Name der Funktion. Du kannst diesen natürlich frei anpassen.
Nutze einen aussagekräftigen Namen und stelle einen Prefix voran, um die Wahrscheinlichkeit einer Kollision mit einem anderen Plugin oder Theme zu minimieren.
Schritt 2: Beschriftungen vorbereiten
Der Custom Post Type erhält einen eigenen Menüpunkt im Backend.
Dementsprechend müssen die Label dafür vorbereitet werden.
$labels = array(
'name' => _x( 'Apartments', 'Post Type General Name', 'wf-apartments' ),
'singular_name' => _x( 'Apartment', 'Post Type Singular Name', 'wf-apartments' ),
'menu_name' => __( 'Apartments', 'wf-apartments' ),
'name_admin_bar' => __( 'Apartments', 'wf-apartments' ),
'archives' => __( 'Apartment archives', 'wf-apartments' ),
'all_items' => __( 'All apartments', 'wf-apartments' ),
'add_new_item' => __( 'Add new apartment', 'wf-apartments' ),
'add_new' => __( 'Add new', 'wf-apartments' ),
'new_item' => __( 'New apartment', 'wf-apartments' ),
'edit_item' => __( 'Edit apartment', 'wf-apartments' ),
'update_item' => __( 'Update apartment', 'wf-apartments' ),
'view_item' => __( 'View apartment', 'wf-apartments' ),
'view_items' => __( 'View apartments', 'wf-apartments' ),
'search_items' => __( 'Search apartments', 'wf-apartments' ),
);
Ich habe mich dazu entschieden, nur die notwendigsten Label anzupassen, um das Tutorial kurz und verständlich zu halten. Die WordPress Ressourcen bieten eine vollständige Liste aller Post Type Label (engl).
Tipp
Falls du dich wunderst, was __()
und _x()
machen: Diese Funktionen markieren übersetzungsfähigen Text. Mehr dazu im Tutorial WordPress übersetzen.
Schritt 3: Editor-Ansicht vorbereiten
Nun ist es an der Zeit festzulegen, welche Funktionen in der Bearbeitungsansicht einer Ferienwohnung zu sehen sein sollen.
Ich entscheide mich für
- den Seitentitel
- den Editor – Classic oder Gutenberg möglich, wird gleich noch festgelegt
- das Beitragsbild
- Revisionen
$supports = array(
'title',
'editor',
// 'excerpt',
// 'author',
'thumbnail',
//'trackbacks',
// 'custom-fields',
'revisions',
// 'page-attributes',
// 'post-formats'
// 'comments'
);
Der Vollständigkeit halber habe ich mal alle Möglichkeiten aus der Liste aller supports
-Optionen (engl) aufgezeigt.
Die nicht benötigten Optionen sind auskommentiert und werden nicht im Backend angezeigt. Du kannst diese Zeilen auch einfach entfernen, um den Code übersichtlicher zu halten.
Tipp
Damit die Beitragsbild-Metabox angezeigt wird, muss das Theme post-thumbnails
unterstützen. Mehr dazu: add_theme_support()
Schritt 4: Permalinks konfigurieren
Die URL-Struktur soll am Ende wie folgt aussehen:
domain.de/apartments/haus-am-strand
$rewrite = array(
'slug' => 'apartments',
'with_front' => true,
'pages' => false,
'feeds' => true,
);
Code-Erklärung:
slug
ist der Teil der URL, der den erstellten Inhalte des Custom Post Types vorangestellt werden soll. Eignet sich gut, um eine Hierarchie in die Seite zu bringen.with_front
entscheidet darüber, ob die vom User in den Permalink-Einstellungen festgelegte „Linkstruktur“ beibehalten werden soll. Ist ein bisschen unglücklich ausgedrückt. Darum ein Beispiel.- Beispiel: Permalink-Einstellungen stehen auf Benutzerdefiniert:
/blog/%postname%
. - Mit
with_front' => true
wird der CPT unter/blog/{slug}/%postname%
angezeigt. - Mit
with_front' => false
wird der CPT unter/{slug}/%postname%
angezeigt.
- Beispiel: Permalink-Einstellungen stehen auf Benutzerdefiniert:
pages
kann die Paginierung für Archivseiten des CPTs erlauben oder verbieten.feeds
gibt an, ob ein RSS-Feed-Link für den CPT erstellt werden soll.
Gut zu wissen: Aktuell ist es scheinbar nicht möglich den Slug standardmäßig übersetzungsfähig zu machen.
Mehr dazu in einem interessanten Thread auf StackExchange.
Schritt 5: Funktion vorbereiten
So. Nun wird alles zusammengeführt und die letzten Einstellungen gesetzt.
$args = array(
'label' => __( 'Apartments', 'wf-apartments' ),
'description' => __( 'Manage your apartments', 'wf-apartments' ),
'labels' => $labels,
'supports' => array( 'title', 'editor' ),
'show_in_rest' => true,
'taxonomies' => array( 'category', 'post_tag' ),
'hierarchical' => false,
'public' => true,
'show_in_menu' => true,
'menu_position' => 5,
'menu_icon' => 'dashicons-admin-home',
'has_archive' => true,
'capability_type' => 'page',
'rewrite' => $rewrite,
);
Code-Erklärung:
label
: Legt den Text für den Menüpunkt fest und überschreibt$labels[name]
, sofern festgelegt.description
: Beschreibt den Sinn und Zweck des Custom Post Types. Keine Ahnung, wo das angezeigt wird…labels
: Liefert die bereits oben deklarierten Beschriftungen für die Verwaltungsoberfläche.supports
: Legt fest, welche Funktionen in der Bearbeitungsfläche verfügbar sein werden.- Der oben gezeigt Code zieht die Konfiguration aus der in Schritt 3 erstellten Variable
$supports
.
- Der oben gezeigt Code zieht die Konfiguration aus der in Schritt 3 erstellten Variable
show_in_rest
: Legt fest, ob der Gutenberg-Editor genutzt werden darf. (Kurz und knapp erklärt aus der Praxissicht.)taxonomies
: Legt fest, ob dem Inhalt Kategorien (category
), Schlagwörter (post_tag
) oder individuelle Taxonomien (die musst du erst erstellen) zugeordnet werden dürfen.hierarchical
: Legt fest, ob Elternelemente festgelegt werden dürfen.public
: Legt fest, ob die erstellten Inhalte für Autoren und Websitesbesucher sichtbar sein dürfen.true
bietet sich für alles an, was ganz normal auf der Seite sichtbar sein wird. Beispielsweise die Ferienwohnungen aus dem Beispiel.false
bietet sich an, wenn nur Daten eingepflegt werden und diese an anderer Stelle zusammen- und ausgeführt werden.public
setzt anhand des zugewiesenen Wertes „Standardregeln“ fürshow_in_nav_menus
,show_ui
,exclude_from_search
undpublicly_queryable
. Du kannst die eben genannten Argumente auch explicit setzen und das Ganze somit granularer anpassen
show_in_menu
: Legt fest, ob der Custom Post Type einen eigenen Menüpunkt im Backend erhalten soll.menu_position
: Legt die Position des Menüpunkts im Backend fest. Bedingung ist natürlich, dassshow_in_menu
nichtfalse
ist.- 5: unter Beiträge
- 10: unter Medien
- 20: unter Seiten
- 25: unter Kommentare (Standard, wenn kein expliziter Wert festgelegt ist)
- 60: unter dem ersten Trenner – also quasi über Design
- 65: unter Plugins
- 70: unter Benutzer
- 75: unter Werkzeuge
- 80: unter Einstellungen
- 100: unter dem zweiten Trenner – also quasi über Menü einklappen
menu_icon
: Legt fest, welches Icon dem Menüpunkt vorangestellt sein soll. Unterstützt werden die Dashicons von WordPress und eigene SVGs als inline-string (base64-codiert).has_archive
: Legt fest, ob die erstellten Inhalte automatisch auf einer Archivseite – ähnlich den Beiträgen – gesammelt und ausgegeben werden sollen.- Bei Ferienwohnungen bietet sich eine Archivseite natürlich an, weil der User so direkt die neuesten Objekte sehen kann. Mit ein paar Anpassungen könnte die Archivseite um Filterfunktionen erweitert werden, um dem User noch nützlicher zu sein.
capability_type
: Lege fest, welche Rolle/Rechte ein Nutzer haben muss, um die Inhalte des Custom Post Types bearbeiten zu können.rewrite
: Legt die Permalink-Regeln fest. Kann auch weggelassen werden.- Wenn du
rewrite
setzt, dann sollte dein Plugin die Permalinks mithilfe von flush_rewrite_rules() eigenständig aktualisieren. Einmal während der Aktivierung und einmal während der Deaktivierung des Plugins. - Wenn die Permalinks nicht automatisch aktualisiert werden, dann muss der WordPress-User die Permalinks nach dem aktivieren und deaktivieren des Plugins manuell aktualisieren. Absolut keine Empfehlung, weil User es vergessen und dich mit Support-Anfragen überfluten werden.
- Wenn du
Schritt 5: Post Type final registrieren
Folgende Zeile Code registriert nun den Custom Post Type.
register_post_type( 'wf_cpt_apartments', $args );
Mit der Registrierung des Custom Post Types wird der eigene Eintrag in der Menüleiste sichtbar.
Zusammenfassung
Zum Abschluss der ganze Code an einem Stück
function wf_register_custom_post_type_apartment() {
$labels = array(
'name' => _x( 'Apartments', 'Post Type General Name', 'wf-apartments' ),
'singular_name' => _x( 'Apartment', 'Post Type Singular Name', 'wf-apartments' ),
'menu_name' => __( 'Apartments', 'wf-apartments' ),
'name_admin_bar' => __( 'Apartments', 'wf-apartments' ),
'archives' => __( 'Apartment archives', 'wf-apartments' ),
'all_items' => __( 'All apartments', 'wf-apartments' ),
'add_new_item' => __( 'Add new apartment', 'wf-apartments' ),
'add_new' => __( 'Add new', 'wf-apartments' ),
'new_item' => __( 'New apartment', 'wf-apartments' ),
'edit_item' => __( 'Edit apartment', 'wf-apartments' ),
'update_item' => __( 'Update apartment', 'wf-apartments' ),
'view_item' => __( 'View apartment', 'wf-apartments' ),
'view_items' => __( 'View apartments', 'wf-apartments' ),
'search_items' => __( 'Search apartments', 'wf-apartments' ),
);
$supports = array(
'title',
'editor',
// 'excerpt',
// 'author',
'thumbnail',
//'trackbacks',
// 'custom-fields',
'revisions',
// 'page-attributes',
// 'post-formats'
// 'comments'
);
$rewrite = array(
'slug' => 'apartments',
'with_front' => true,
'pages' => false,
'feeds' => true,
);
$args = array(
'label' => __( 'Apartment', 'wf-apartments' ),
'description' => __( 'Manage your apartments', 'wf-apartments' ),
'labels' => $labels,
'supports' => array( 'title', 'editor' ),
'show_in_rest' => true,
'taxonomies' => array( 'category', 'post_tag' ),
'hierarchical' => false,
'public' => true,
'show_in_menu' => true,
'menu_position' => 5,
'menu_icon' => 'dashicons-admin-home',
'has_archive' => true,
'capability_type' => 'page',
'rewrite' => $rewrite,
);
register_post_type( 'wf_cpt_apartments', $args );
}
add_action( 'init', 'wf_register_custom_post_type_apartment', 0 );
Metabox für deinen Custom Post Type erstellen
Sobald der Custom Post Type registriert ist, geht es daran das Backend entsprechend zu erweitern.
Dazu eignen sich Metaboxen wunderbar.
Für eine Ferienwohnung könnten beispielsweise die Anzahl der Zimmer, die Wohnfläche in m² oder auch der Preis pro Nacht in Metaboxen festgehalten werden.
Zu Demonstrationszwecken erstelle ich ein einfaches Eingabefeld für den Titel des Hauses.
So kann der User seine interne Bezeichnung für das Haus von der für den Websitesbesucher sichtbaren Bezeichnung trennen.
Das macht zum Beispiel Sinn, wenn der User die Objekte intern mit Immobilien-IDs als Titel anlegen will und dem Websitesbesucher gleichzeitig eine attraktive h1
-Überschrift angezeigt werden soll.
Schritt 1: Metabox „registrieren“ und mit CPT verknüpfen
Kurz vorab: Eine Metabox kann mehrere Eingabefelder haben. Für viele Einsatzzwecke reicht es also aus, eine zu registrieren.
function wf_add_apartment_metabox() {
add_meta_box(
'wf_apartment_metabox',
_x( 'Apartment features', 'Backend: Title for Metabox panel' , 'wf-apartments' ),
'wf_display_apartment_metabox',
array( 'wf_cpt_apartments' ),
'normal',
'default'
);
}
Code-Erklärung:
wf_apartment_metabox
ist die ID der Metabox. Wert darf individuell bennant werden und sollte einmalig sein._x(...)
gibt der Metabox einen Namen. Wird beispielsweise als Screenreader-Text für den einblenden/ausblenden Button des Panels genutzt.wf_display_apartment_metabox
ist die Callback-Funktion. In dieser ist das HTML-Gerüst der Metabox hinterlegt.array( 'wf_cpt_apartments' )
gibt an, für welche Post Types die Metaboxen angezeigt werden sollen.normal
ist Anzeigeposition im Backend.normal
undadvanced
zeigen die Metabox unter dem Editor an – kein Unterschied im Gutenberg erkennbar.side
verlagert die Metabox in die Seitenleiste mit den Dokument-Einstellungen
default
beschreibt die Priorität der Metabox. Hat beispielsweise eine Auswirkung auf die Reihenfolge, wenn mehrere Metaboxen die selbe Position in Anspruch nehmen wollen.- mögliche werte:
default
,low
,high
,core
- mögliche werte:
Teile dem Custom Post Type anschließend noch mit, dass er eine eigene Metabox hat.
Erweitere dazu $args
um folgende Zeile:
'register_meta_box_cb' => 'wf_add_apartment_metabox',
Code Erklärung
wf_add_apartment_metabox
ist der Funktionsname, der deine Metabox hinzufügt.
Schritt 2: HTML-Gerüst der Metabox festlegen
Die bei der Registrierung der Metabox hinterlegte Callback-Funktion trägt das HTML-Gerüst.
Da es diese Funktion nicht gibt, musst du sie noch erstellen.
function wf_display_apartment_metabox( $post ) {
wp_nonce_field( basename( __FILE__ ), 'wf_apartments_metabox_nonce' );
$html = '<p><label>' . esc_html( 'Apartment title' , 'wf-apartments' ) . ' <input type="text" aria-describedby="title-description" name="wf_apartment_title" value="' . esc_attr( get_post_meta($post->ID, 'wf_apartment_title',true) ) . '" /></label></p>';
$html .= '<p class="description" id="title-description">' . esc_html( 'This title will be shown to your website visitors.' , 'wf-apartments' ) . '</p>';
echo $html;
}
Die Funktion besteht einfach aus dem nonce-Feld und deinem HTML.
Das nonce-Feld ist ein verstecktes Formularfeld, das zur Absicherung der Eingaben eingesetzt wird. Mehr dazu: wp_nonce_field()
Das HTML kann nun die Eingabefelder beinhalten, die du für deine Metabox benötigst.
Wichtig:
- Gib allen Eingabefeldern ein
name
-Attribut mit einem einmaligen Wert, damit WordPress weiß unter welchem „Bezeichner“ der vom User eingegebene Inhalt in der Datenbank gespeichert werden soll. - Nutze den „Bezeichner“, um mithilfe von
get_post_meta()
den gespeicherten Wert aus der Datenbank auszulesen und als Inhalt im Eingabefeld anzuzeigen. (Sonst wird der vom User gesetzte Inhalt nicht im Backend angezeigt, wenn er den Beitrag erneut bearbeitet.)- Setze dafür beispielsweise ein
value
-Attribut bei Textfeldern und ordne diesem als Wert den aus der Datenbank ausgelesenen Inhalt zu. - Oder setze das
checked
-Attribut bei einer Checkbox, wenn der ausgelesene Wert1
ist.
- Setze dafür beispielsweise ein
Schritt 3: Speichern der Daten erlauben
Da das HTML-Gerüst steht, kann es schon im Backend angezeigt werden.
Doch damit die Werte beim speichern des Beitrags an die Datenbank gesendet werden, ist noch eine letzte Funktion notwendig.
Kurze Erklärung, was die Funktion machen soll:
- Allgemeiner Sicherheits-Check: Prüfen, ob das nonce-Feld den im HTML-Gerüst festgelegten Wert hat
- Benutzerrechte-Check: Festlegen und sicherstellen, dass der User die entsprechenden Rechte hat, um die Merkmale der Ferienwohnung zu bearbeiten.
- Frontend absichern: Verhindern, dass die automatische Zwischenspeicherung Inhalte in der Datenbank überschreibt und damit die Frontend-Ausgabe der Live-Version verändert.
- Wenn alle Checks erfolgreich bestanden sind, dann werden die Daten an die Datenbank gesendet und gespeichert.
Erstelle dafür eine neue Funktion, die über die save_post()
-Hook geladen wird.
function wf_save_apartments_post_meta( $post_id, $post ) {
//...
return $post_id;
}
add_action( 'save_post_wf_cpt_apartments', 'wf_save_apartments_post_meta', 10, 2 );
Tipp
Um Ressourcen zu sparen, kannst du save_post_[cpt_name]()
anstatt der einfachen save_post()
-Hook verwenden. Dann wird das Script nur beim festgelegten Custom Post Type ausgeführt.
Nun wird die Funktion mit Inhalt gefüllt
nonce-Feld prüfen
if ( !isset( $_POST['wf_apartments_metabox_nonce'] ) || !wp_verify_nonce( $_POST['wf_apartments_metabox_nonce'], basename( __FILE__ ) ) ) {
return $post_id;
}
Benutzerrechte prüfen
Wenn der Nutzer keine Beiträge bearbeiten darf, dann wird auch nichts gespeichert.
$post_type = get_post_type_object( $post->post_type );
if ( !current_user_can( $post_type->cap->edit_post, $post_id ) ) {
return $post_id;
}
Automatisches Datenüberschreiben verhindern
Wenn der Speichervorgang eine automatische Speicherung ist, dann werden die Metadaten nicht überschrieben, damit der User die volle Kontrolle darüber hat, wann er die Daten veröffentlicht.
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
return $post_id;
}
Eingaben an die Datenbank senden
Wenn bis jetzt noch nicht abgebrochen wurde, und der richtige Post Type bearbeitet wird, dann kann gespeichert werden.
if ($post->post_type == 'wf_cpt_apartments') {
update_post_meta($post_id, 'wf_apartment_title', sanitize_text_field( $_POST['wf_apartment_title'] ) );
}
- Nutze anstelle von
wf_apartment_title
den Bezeichner deines Metadatums. - Mit sanitize_text_field() wird der eingegeben Wert ein wenig bereinigt, falls notwendig.
- Es gibt auch Funktionen für das prüfen und bereinigen vom Mail-Input, Dateinamen, etc.
- Mehr dazu im Codex: Validating Sanitizing and Escaping User Data
Tipp
Wenn du mehr als nur ein Eingabefeld benötigst, dann kannst du einfach das HTML-Grundgerüst erweitern und weitere Zeilen mit update_post_meta()
in die if-Bedingung des Snippets einfügen.
Zusammenfassung: Speicherfunktion auf einen Blick
function wf_save_apartments_post_meta( $post_id, $post ) {
// security: check nonce field
if ( !isset( $_POST['wf_apartments_metabox_nonce'] ) || !wp_verify_nonce( $_POST['wf_apartments_metabox_nonce'], basename( __FILE__ ) ) ) {
return $post_id;
}
// security: check user permissions
$post_type = get_post_type_object( $post->post_type );
if ( !current_user_can( $post_type->cap->edit_post, $post_id ) ) {
return $post_id;
}
// prevent updating post meta on autosave
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
return $post_id;
}
// update post meta
if ($post->post_type == 'wf_cpt_apartments') {
update_post_meta($post_id, 'wf_apartment_title', sanitize_text_field( $_POST['wf_apartment_title'] ) );
}
return $post_id;
}
add_action( 'save_post_wf_cpt_apartments', 'wf_save_apartments_post_meta', 10, 2 );
Eigene Templates für deinen CPT anlegen
WordPress durchsucht standardmäßig das aktive Theme nach Templates.
Das betrifft sowohl die Basis-Templates, wie beispielsweise archive.php
und single.php
aber auch individuelle Templates, die von Themes bereitgestellt werden.
Theme Autoren können zur Template-Erstellung einfach eine PHP-Datei mit (fast) beliebigen Namen im Theme-Ordner hinterlegen und diese mit einer einfachen Info als Template kenntlich machen.
Fast beliebiger Name, weil WordPress einige Dateinamen für gängige Templates (engl) nutzt/reserviert. Diese zu verwenden, könnte für Probleme sorgen.
<?php
/**
* Template Name: Apartment
* Template Post Type: wf_cpt_apartments
*/
Code-Erklärung
Template Name
darf frei gewählt werden und ist automatisch – also auch ohne ohne__()
– übersetzungsfähig.Template Post Type
ist optional und erlaubt es festzulegen, für welche Beitragsarten das Template genutzt werden darf.
Tipp
Template-Infos können einfach in einem Kommentar hinterlegt werden. Ähnlich einem Plugin Header.
So. Nun habe ich über Themes gesprochen. Plugins durchsucht WordPress standardmäßig nicht nach Template-Dateien.
Für den Fall, dass du deinen Custom Post Type in einem Plugin hältst, kannst du eine Funktion schreiben, die folgendes macht:
- Dateinamen für deine CPT Template-Dateien festlegen. Zum Beispiel
wf-apartment-single.php
undwf-apartment-archive.php
. - Prüfen, ob das aktive Theme die Dateien besitzt.
- Wenn ja, dann diese Template-Dateien zur Ausgabe verwenden.
- Wenn nein, dann die im Plugin mitgelieferten Dateien nutzen.
Mit diesem Ansatz erlaubst du den Usern deines Plugins die Ausgabe zu steuern, weil sie deine Template-Dateien aus dem Plugin kopieren, anpassen, in ihr Theme laden, und die Ausgabe einfach anpassen können.
Einen Beispielcode dafür gibt es auf Pixelbar: Templates in Plugins
Die Daten der Metaboxen kannst du dann mit get_post_meta()
erhalten und ganz einfach im Template verwenden:
<php
$price_per_night = get_post_meta( $post_id, $meta_key, true);
// more meta data...
?>
Die Ausgabe könnte wie folgt aussehen:
<p class="wf_apartment_data__pricing">
<span class="wf_apartment_data__label"><php _e( 'Price per night' , 'wf-apartments' ); ?></span>
<span class="wf_apartment_data__value"><php esc_html_e( $price_per_night ); ?></span>
</p>
Diesen Artikel in sozialen Netzwerken teilen: