Kurzanleitung: WordPress Post Types oder „Bau dir deine WordPress-Welt“

Das Post-Type Konzept, auf dem die Datenstruktur von WordPress basiert, hat den großen Vorteil, dass es sehr einfach ist. Diese Einfachheit ermöglicht es alles Mögliche, in relativ kurzer Zeit und gut nachvollziehbar, in dieses Content Management System zu integrieren.
Die Post-Type Denkweise geht davon aus, das man (fast) alles als Entität mit gewissen Eigenschaften (Meta-Informationen) abbilden kann, wie zum Beispiel in einer Klasse.
Ein gewöhnlicher Blog-Post hat einen Titel und Inhalt. Ein Post-Typ Person könnte z.B. eine Adresse und eine Telefonnummer haben. In der Datenbank würde das wie folgt aussehen:

Um einen neuen Post-Typ zu integrieren muss man ihn bei WordPress registrieren. Nach der Registrierung erhält er im Backend einen Menüeintrag und kann im Prinzip auch schon verwendet werden:

public function register_person_post_type()
{
	$labels = array(
			'name'               => _x( 'Personen', 'post type general name', 'your_textdomain' ),
			'singular_name'      => _x( 'Person', 'post type singular name', 'your_textdomain' ),
			'menu_name'          => _x( 'Personen', 'admin menu', 'your_textdomain' ),
			'name_admin_bar'     => _x( 'Personhinzufügen', 'add new on admin bar', 'your_textdomain' ),
			'add_new'            => _x( 'Neu hinzufügen', 'person', 'your_textdomain' ),
			'add_new_item'       => __( 'Neuen Personenhinzufügen', 'your_textdomain' ),
			'new_item'           => __( 'Neuer Person', 'your_textdomain' ),
			'edit_item'          => __( 'Personbearbeiten', 'your_textdomain' ),
			'view_item'          => __( 'Personanzeigen', 'your_textdomain' ),
			'all_items'          => __( 'Alle Personen', 'your_textdomain' ),
			'search_items'       => __( 'Personensuchen', 'your_textdomain' ),
			'parent_item_colon'  => __( 'Eltern Personen:', 'your_textdomain' ),
			'not_found'          => __( 'Keine Personen gefunden.', 'your_textdomain' ),
			'not_found_in_trash' => __( 'Keine Personen im Papierkorb gefunden.', 'your_textdomain' )
	);

	$args = array(
			'labels'             => $labels,
			'description'        => __( 'Beschreibung.', 'your_textdomain' ),
			'public'             => true,
			'publicly_queryable' => true,
			'show_ui'            => true,
			'show_in_menu'       => true,
			'query_var'          => true,
			'rewrite'            => array( 'slug' => 'person' ),
			'capability_type'    => 'post',
			'has_archive'        => true,
			'hierarchical'       => false,
			'menu_icon'          => plugins_url('images/person_icon.png', __FILE__),
			'menu_position'      => null,
			'supports'           => array( 'title', 'editor', 'author', 'thumbnail' )
	);

	register_post_type( 'person', $args );
}
add_action('init', 'register_person_post_type');

Viele der hier verwendeten Argumente (Variable $labels und $args) sind optional und müssen nicht zwangsläufig immer verwendet werden. Es empfiehlt sich allerdings alles mit den, für den aktuellen Fall, sinnvoll erscheinenden Werten zu versehen.

  • Das $labels Array definiert die für den Post Type relevanten Begriffe in Ein- und Mehrzahl. Sie werden von WordPress dann in die entsprechenden Buttons und Beschriftungen im Backend eingefügt. Funktionen __() und _x(), die die Begriffe umschließen, dienen einer späteren Übersetzung in andere Sprachen und sind nicht zwingend erforderlich. Trotzdem sollte man sie verwenden.
    Es wäre nicht das erste Mal, dass sich erst nach einiger Zeit herausstellt, dass eine Webseite mehrsprachig gemacht werden soll. Hat man dann die Funktionen zur Übersetzung nicht gesetzt,
    muss man Sie mühsam überall im Code nachtragen!
  • Die Post Type Beschreibung wird normalerweise nirgendwo anzeigt, es sei denn man gibt sie explizit aus
  • Die public Eigenschaft legt die Sichtbarkeit des Post Types fest, wobei public hier eher als globaler „Schalter“ anzusehen ist. Er schaltet die Sichtbarkeit des Post Types in all ihren Nuancen (Auffindbar in Suchergebnissen des Frontends, Sichtbarkeit für Authoren, uvm.) generell ein oder aus. Möchte man hier eher Fine Tuning betreiben stehen weitere Eigenschaften bereit:
    • exclude_from_search: Diesen Post Type nicht berücksichtigen bei der Suche auf der Webseite
    • publicly_queryable: Kann auf der Webseite von WP_Query verwendet werden, z.B. um Archive oder Einzelseiten des Typs anzuzeigen.
    • show_in_nav_menus: Kann in Menüs der Webseite angezeigt werden. Ist diese Option false, wird der Post Type in den Menüeinstellungen nicht vorgeschlagen.
    • show_ui: Backend Menü des Typs ein- oder ausschalten.
  • Mit query_var lässt sich der Schlüssel für die Query Variable des Post Types festlegen
  • Mit der rewrite Option legt ihr den URL-Slug für euren Post Typ fest. Nach diesen Code wäre der Slug für das Archiv www.karl-mustermann.de/person/ und für eine einzelne Person www.karl-mustermann.de/person/karl-mustermann
  • Die Einstellung capability_type ermöglicht es, auf einen Schlag Benutzerrechte festzulegen. Aktuell habe ich WordPress z.B. mitgeteilt, dass es den Person-Typ berechtigungsmäßig wie den Standard-Beitragstyp behandeln kann.
  • has_archive gibt WordPress Bescheid ob der Typ ein Archiv haben soll, also eine Übersicht im Frontend, die alle Posts dieses Typs auflistet, z.B. www.karl-mustermann.de/person/
  • Wenn ein Post Typ hierachisch ist, kann man seine Posts in Eltern- und Kind Beiträge gliedern, wie es zum Beispiel beim mitgelieferten WordPress Post Type „Seite“ der Fall ist
  • Ihr könnt ein Icon für das Backendmenü festlegen (menu_icon) und festlegen an welcher Stelle euer Menüpunkt im Backend-Menü angezeigt wird (menu_position).
  • Zu guter letzt kann noch angegeben werden ob bestimmter Standard-Komponenten eines Beitrags unterstützt werden sollen, z.B. ob ihr ein Beitragsbild für eine Person festlegen wollt oder ob euer Typ einen Post Titel haben soll.

Damit der neue Personen-Typ auch seine Meta-Informationen, also Adresse und Telefonnummer, erhält müssen dafür noch benutzerdefinierte Felder angelegt werden, damit man die Daten hinterlegen kann. Zunächst erstellen wir eine Metabox, in der die Felder platziert werden:

public static function add_lecturer_meta_boxes()
{
     function add_person_meta_box() {
	add_meta_box(
		'person_meta_box_main',
		__('Person', 'your_textdomain'),
		'person_meta_box_callback',
		'person',
		'normal',
		'high'
	);
     }
}
add_action('add_meta_boxes', 'add_person_meta_box');
  • Wir vergeben mit dem ersten Parameter eine ID an die Metabox.
  • Das zweite Argument, legt den Überschriften-Text der Metabox fest.
  • Nummer 3 gibt einen Funktionsnamen an, der den Inhalt der Box ausgeben soll. Das heißt, die Box wird hier angelegt und danach wird die Callback Funktion ausgeführt um die Inhalte zu definieren.
  • Argument 4 legt fest, dass die Metabox (nur) bei Beiträgen vom Typ Person angezeigt wird
  • Parameter Nummer 5 gibt an wo die Box angezeigt werden soll (z.B. in der Sidebar oder im Content-Bereich)
  • Der sechste Parameter beeinflusst die Reihenfolge der Box im Zusammenspiel mit anderen Boxen.
  • Das letzte Argument (wird hier nicht verwendet) kann Parameter für die im 3. Argument angegebene Callback-Funktion enthalten

Nun befassen wir uns mit der angegebenen Callback Funktion, die der Metabox die Inhalte serviert:

function person_meta_box_callback()
{
	global $post;
	
	echo '<input type="hidden" name="person_noncename" value="' .	wp_create_nonce( 'Beliebige Zeichenkette' ) . '" />';
	
	$adress = get_post_meta($post->ID, 'person_adress', true);
	$phone = get_post_meta($post->ID, 'person_phone', true);
		
	echo '<label for="person[adress]">' . __('Adresse.', 'my_textdomain') . '</label>';
	echo '<textarea name="person[adress]" value="' . $adress  . '"</textarea>';
	
	echo '<label for="person[phone]">' . __('Telefon', 'my_textdomain') . '</label>';
	echo '<input type="text" id="person_provider_phone" name="person[phone]" value="' . $phone  . '" />';

}
  • Zuerst wir eine Nonce festgelegt. Sie ist im Prinzip optional, aber empfehlenswert. WordPress kann so den Ursprung der Daten nach dem absenden feststellen und somit sicherstellen, dass es sich nicht um einen Angriff von außen handelt.
  • Zunächst werden jetzt die aktuellen Wert der Felder geholt um die Steuerelemente zu befüllen, danach werden eben diese Steuerelemente ausgegeben.

Danach muss man WordPress noch beibringen, die eingegebenen Meta-Daten auch zu speichern.

public static function save_person_fields($post_id)
{
	// Ist ein Nonce Feld übergeben worden?
	if(!isset($_POST['person_noncename']))
	{
		return $post_id;
	}
	
	// Ist die Nonce korrekt?
	if ( !wp_verify_nonce( $_POST['person_noncename'], 'Beliebige Zeichenkette' )) {
		return $post_id;
	}
	
	// Hat der aktuelle Benutzer das Recht Beiträge zu bearbeiten?
	if ( !current_user_can( 'edit_post', $post_id )) {
		return $post_id;
	}
	
	// Empfangene Daten
	$person_metadata = $_POST['person'];

	// Sind Daten angekommen?
	if(is_array($person_metadata) && count($person_metadata) > 0)
	{
		// Lauf über die empfangenen Daten
		foreach ($person_metadata as $key => $val) {
			// Entferne gefährliche Inhalte und schreibe die Daten in die Datenbank
			$value = sanitize_text_field($val);
						
			$dbkey = 'person_' . trim($key);
			$dbval = $value;
			
			update_post_meta($post_id, $dbkey, $dbval);
		}
	} else {
		return $post_id;
	}
}

add_action('save_post', 'save_person_fields');

All diese Schritte werden mit add_action an Hooks geknüpft. Ereignisse die WordPress vorgibt, um sich an bestimmten Stellen, des Ladevorgangs „einzuhaken“ und das System über die gewünschten Funktionen zu informieren.

Fertig! Gib deine Personen ein und tue was du tun wolltest!
Zur Ausgabe der Daten im Frontend, musste du ggf. die Template Dateien deines Themes bearbeiten. Das beschreibe ich in einem anderen Beitrag.

Schreibe einen Kommentar