Begriffe vorab
- Shortcode: ein Platzhalter wie
[merkzettel], den WordPress beim Ausgeben durch Code ersetzt. - Enqueue: das geordnete Einbinden von Skripten und Styles über WordPress.
- AJAX: Daten im Hintergrund an den Server senden, ohne die Seite neu zu laden.
- REST-Route: eine URL der WordPress-REST-API, an die ein Plugin eigene Funktionen hängt.
- Nonce: kurzlebiges Token, das die Herkunft einer Anfrage bestätigt.
Shortcode, der nur bei Bedarf Assets lädt
Ein häufiger Fehler ist, Skripte auf jeder Seite zu laden. Besser: Skript registrieren und erst im Shortcode einreihen. So wird es nur dort geladen, wo der Shortcode steht.
add_action( 'wp_enqueue_scripts', function () {
wp_register_script( 'mz-js', MZ_URL . 'assets/merkzettel.js', array(), MZ_VERSION,
array( 'in_footer' => true, 'strategy' => 'defer' ) );
} );
add_shortcode( 'merkzettel', function ( $atts ) {
$atts = shortcode_atts( array( 'titel' => 'Meine Merkliste' ), $atts, 'merkzettel' );
if ( ! is_user_logged_in() ) {
return '<p>Bitte anmelden.</p>';
}
wp_enqueue_script( 'mz-js' );
wp_add_inline_script( 'mz-js', 'window.MZ=' . wp_json_encode( array(
'rest' => esc_url_raw( rest_url( 'merkzettel/v1/items' ) ),
'nonce' => wp_create_nonce( 'wp_rest' ),
) ) . ';', 'before' );
return '<div class="mz"><h3>' . esc_html( $atts['titel'] ) . '</h3><ul id="mz-list"></ul></div>';
} );
Wichtig: Ein Shortcode-Callback gibt zurück, er gibt nicht aus. wp_json_encode() und esc_url_raw() sorgen dafür, dass Werte sicher im Skript landen.
REST statt admin-ajax
Für neue Plugins ist die REST API der empfohlene Weg: klare URLs, Versionierung, Rechteprüfung pro Route. Die Route wird auf rest_api_init registriert; der permission_callback ist verpflichtend.
add_action( 'rest_api_init', function () {
register_rest_route( 'merkzettel/v1', '/items', array(
array(
'methods' => 'POST',
'callback' => 'mz_add_item',
'permission_callback' => fn() => is_user_logged_in(),
'args' => array(
'post_id' => array( 'required' => true, 'sanitize_callback' => 'absint' ),
),
),
) );
} );
function mz_add_item( WP_REST_Request $req ) {
$post_id = (int) $req['post_id'];
if ( ! get_post_status( $post_id ) ) {
return new WP_Error( 'mz_not_found', 'Beitrag nicht gefunden.', array( 'status' => 404 ) );
}
MZ_Store::add( get_current_user_id(), $post_id );
return rest_ensure_response( array( 'ok' => true ) );
}
Bei Cookie-Anmeldung muss jede Anfrage das Nonce zur Aktion wp_rest mitsenden, entweder im Header X-WP-Nonce oder als Parameter _wpnonce. Fehlt es, setzt WordPress den Nutzer auf 0 – die Anfrage gilt als anonym, auch wenn man angemeldet ist.
Wenn doch admin-ajax.php
Bestehender Code nutzt oft die Hooks wp_ajax_{aktion} (angemeldet) und wp_ajax_nopriv_{aktion} (nicht angemeldet) mit admin-ajax.php. Das funktioniert weiter, bietet aber weniger Struktur als REST. Auch dort gehören Nonce-Prüfung und Rechtekontrolle in den Handler.
Zum Selbermachen
- Baue den Shortcode und prüfe im Seitenquelltext, dass das Skript nur auf Seiten mit Shortcode erscheint.
- Rufe die Route ohne Nonce auf und beobachte die Antwort.
- Sende einen ungültigen
post_idund prüfe den 404-Fehler.
Prüfstatus: Belegt (Stand 1. Oktober 2026): Jahreszahlen, Zahlen, Namen und Quellenangaben dieser Lektion, soweit die Quellenliste sie nennt, wurden gegen Primärquellen geprüft. Nicht einzeln belegt: erklärende Darstellung nach Lehrbuchstand und Quellen, die in der Liste als „allgemeine Referenz“ markiert sind. Codebeispiele sind nur auf Syntax geprüft, nicht in WordPress ausgeführt.
Quellen
- WordPress Plugin Handbook – „Shortcodes“ (developer.wordpress.org/plugins/shortcodes/) (allgemeine Referenz, nicht Zeile für Zeile geprüft)
- WordPress REST API Handbook – „Adding Custom Endpoints“ und „Authentication“ (developer.wordpress.org/rest-api/) (allgemeine Referenz, nicht Zeile für Zeile geprüft)
- WordPress Developer Resources – Funktionsreferenz zu wp_register_script() (Ladestrategie ab WordPress 6.3) (allgemeine Referenz, nicht Zeile für Zeile geprüft)