1. Home
  2. Docs
  3. Development
  4. Plugin Entwicklung Lernen
  5. Aufgabe 3 – Custom Post Type -Event Plugin

Aufgabe 3 – Custom Post Type -Event Plugin

Du entwickelst ein vollständiges Plugin für ein kleines Veranstaltungsportal. Es soll einen Custom Post Type „Event“ registrieren, eigene Meta-Felder verwalten und eine Admin-Settings-Seite anbieten.

Aufgabenstellung

  1. Recherche: Vergleiche register_post_type() mit dem Plugin „CPT UI“ – wann setzt man welchen Ansatz ein?
  2. Implementierung: Erstelle den CPT „Event“ mit Labels, Supports (title, editor, thumbnail) und Custom Meta-Feldern (Datum, Ort, max. Teilnehmerzahl).
  3. Settings-Page: Baue eine Admin-Seite mit add_options_page() für eine konfigurierbare Datumsformat-Einstellung. Speichere Optionen sicher mit sanitize_text_field().
  4. Reflexion: Dokumentiere Entscheidungen (Warum diese Hooks? Welche Alternativen gäbe es?).

Lernziele

Custom Post TypesMeta-FelderSettings APISanitizationTechnische Doku

Abgabe: Plugin als .zip + technische Dokumentation (1–2 Seiten) + Code-Review in Partnerarbeit

Musterlösung

event-plugin/event-plugin.php

<?php
/**
 * Plugin Name: Event Plugin
 * Description: Custom Post Type fuer Veranstaltungen mit Settings-Page
 * Version:     1.0
 */

if ( ! defined( 'ABSPATH' ) ) exit;

// 1. Custom Post Type registrieren
add_action( 'init', 'eventplugin_register_cpt' );
function eventplugin_register_cpt() {
    register_post_type( 'event', [
        'labels'       => [
            'name'          => 'Events',
            'singular_name' => 'Event',
            'add_new_item'  => 'Event hinzufügen',
            'edit_item'     => 'Event bearbeiten',
        ],
        'public'       => true,
        'has_archive'  => true,
        'supports'     => [ 'title', 'editor', 'thumbnail' ],
        'menu_icon'    => 'dashicons-calendar-alt',
        'show_in_rest' => true, // Gutenberg-Kompatibilität
    ]);
}

// 2. Meta-Felder registrieren
add_action( 'init', 'eventplugin_register_meta' );
function eventplugin_register_meta() {
    foreach ( [ 'event_datum', 'event_ort', 'event_max_teilnehmer' ] as $key ) {
        register_post_meta( 'event', $key, [
            'show_in_rest' => true,
            'single'       => true,
            'type'         => $key === 'event_max_teilnehmer' ? 'integer' : 'string',
            'auth_callback'=> function() { return current_user_can( 'edit_posts' ); },
        ]);
    }
}

// 3. Meta-Box im Editor anzeigen
add_action( 'add_meta_boxes', 'eventplugin_meta_box' );
function eventplugin_meta_box() {
    add_meta_box( 'event-details', 'Event-Details', 'eventplugin_meta_box_html', 'event' );
}
function eventplugin_meta_box_html( $post ) {
    wp_nonce_field( 'eventplugin_save', 'eventplugin_nonce' );
    $datum    = get_post_meta( $post->ID, 'event_datum', true );
    $ort      = get_post_meta( $post->ID, 'event_ort', true );
    $max      = get_post_meta( $post->ID, 'event_max_teilnehmer', true );
    echo '<p><label>Datum: <input type="date" name="event_datum" value="' . esc_attr($datum) . '"></label></p>
    <p><label>Ort: <input type="text" name="event_ort" value="' . esc_attr($ort) . '"></label></p>
    <p><label>Max. Teilnehmer: <input type="number" name="event_max_teilnehmer" value="' . esc_attr($max) . '"></label></p>';
}

// 4. Meta-Felder speichern
add_action( 'save_post_event', 'eventplugin_save_meta' );
function eventplugin_save_meta( $post_id ) {
    if ( ! isset( $_POST['eventplugin_nonce'] ) ) return;
    if ( ! wp_verify_nonce( $_POST['eventplugin_nonce'], 'eventplugin_save' ) ) return;
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;

    update_post_meta( $post_id, 'event_datum',
        sanitize_text_field( $_POST['event_datum'] ?? '' ) );
    update_post_meta( $post_id, 'event_ort',
        sanitize_text_field( $_POST['event_ort'] ?? '' ) );
    update_post_meta( $post_id, 'event_max_teilnehmer',
        absint( $_POST['event_max_teilnehmer'] ?? 0 ) );
}

// 5. Settings-Page
add_action( 'admin_menu', 'eventplugin_settings_menu' );
function eventplugin_settings_menu() {
    add_options_page( 'Event Plugin', 'Event Plugin', 'manage_options',
        'event-plugin-settings', 'eventplugin_settings_page' );
}
function eventplugin_settings_page() {
    if ( ! current_user_can( 'manage_options' ) ) return;
    if ( isset( $_POST['ep_save'] ) &&
         check_admin_referer( 'ep_settings_save' ) ) {
        update_option( 'ep_datumsformat',
            sanitize_text_field( $_POST['ep_datumsformat'] ?? 'd.m.Y' ) );
        echo '<div class="notice notice-success"><p>Gespeichert!</p></div>';
    }
    $format = get_option( 'ep_datumsformat', 'd.m.Y' );
    echo '<div class="wrap">
    <h1>Event Plugin – Einstellungen</h1>
    <form method="post">';
    wp_nonce_field( 'ep_settings_save' );
    echo '<table class="form-table"><tr>
        <th>Datumsformat</th>
        <td><input name="ep_datumsformat" value="' . esc_attr($format) . '">
        <p class="description">Beispiel: d.m.Y = ' . esc_html(date($format)) . '</p></td>
    </tr></table>
    <input type="submit" name="ep_save" class="button-primary" value="Speichern">
    </form></div>';
}

Entscheidungsbegründung: register_post_type() vs. CPT UI

Eigener Code ist sinnvoll, wenn das Plugin auf produktiven Seiten eingesetzt wird, die Abhängigkeit von Dritt-Plugins vermieden werden soll und die Konfiguration im Deployment-Prozess versioniert werden muss.

CPT UI eignet sich für schnelle Prototypen oder wenn nicht-technische Redakteure selbst Post Types anlegen müssen – die Konfiguration wird in der Datenbank gespeichert, was bei Migrationen Aufwand verursacht.

How can we help?