WordPress-Hooks erklärt: Unterschied zwischen Actions und Filtern
Actions führen Code aus, Filter verändern Werte: wie add_action und add_filter funktionieren, was Priorität und Argumentzahl bewirken und wie Sie eigene Hooks anbieten.
Actions und Filter sind die beiden Arten von Hooks in WordPress. Eine Action ist ein Ereignis: WordPress meldet „jetzt passiert X“ und führt alle angehängten Funktionen aus, ein Rückgabewert wird nicht erwartet. Ein Filter reicht einen Wert weiter: Jede angehängte Funktion bekommt ihn, darf ihn verändern und muss ihn zurückgeben. Merkhilfe: Actions tun etwas, Filter verändern etwas.
Wer dieses Prinzip verstanden hat, versteht den Aufbau praktisch jedes Plugins. Den Einstieg in Ordnerstruktur und Header zeigt der Artikel WordPress-Plugin erstellen.
Actions und Filter im direkten Vergleich
| Action | Filter | |
|---|---|---|
| Zweck | Code zu einem Zeitpunkt ausführen | einen Wert verändern |
| Anhängen | add_action() |
add_filter() |
| Auslösen im Kern | do_action() |
apply_filters() |
| Rückgabewert | wird ignoriert | ist Pflicht |
| Typische Beispiele | init, save_post, wp_enqueue_scripts |
the_content, the_title, body_class |
| Typischer Fehler | Ausgabe zur falschen Zeit | Wert nicht zurückgegeben |
Intern sind beide eng verwandt. add_action() ruft im Kern sogar add_filter() auf. Der Unterschied liegt in der Erwartung an Ihre Funktion.
Eine Action anhängen
add_action( 'wp_enqueue_scripts', 'meinplugin_assets' );
function meinplugin_assets() {
wp_enqueue_style(
'meinplugin',
plugins_url( 'assets/style.css', __FILE__ ),
array(),
'1.0.0'
);
}
WordPress löst wp_enqueue_scripts aus, wenn im Frontend Skripte und Styles registriert werden sollen. Ihre Funktion läuft genau dann. Ein anderes Beispiel ist save_post, das nach dem Speichern eines Beitrags feuert und Ihnen die Beitrags-ID übergibt.
Einen Filter anhängen
add_filter( 'the_title', 'meinplugin_titel_markieren', 10, 2 );
function meinplugin_titel_markieren( $titel, $post_id ) {
if ( is_admin() || 'post' !== get_post_type( $post_id ) ) {
return $titel;
}
if ( has_tag( 'aktualisiert', $post_id ) ) {
$titel .= ' (aktualisiert)';
}
return $titel;
}
Wichtig ist das return $titel; in jedem Zweig. Fehlt es, liefert die Funktion null, und der Titel ist leer.
Die vier Parameter von add_action und add_filter
add_filter( $hook_name, $callback, $priority = 10, $accepted_args = 1 );
- Hook-Name: der Name, den WordPress auslöst, etwa
the_content. - Callback: ein Funktionsname als String, ein Array aus Objekt und Methode, eine statische Methode oder eine anonyme Funktion.
- Priorität: bestimmt die Reihenfolge. Niedrige Zahlen laufen zuerst, Standard ist 10. Funktionen mit gleicher Priorität laufen in der Reihenfolge, in der sie angehängt wurden.
- Anzahl Argumente: wie viele Parameter Ihre Funktion erhalten soll. Standard ist 1. Liefert ein Hook mehr Daten, etwa
save_postdie ID, das Beitragsobjekt und die Information, ob es ein Update ist, müssen Sie die Zahl erhöhen, um sie zu bekommen.
add_action( 'save_post', 'meinplugin_beim_speichern', 10, 3 );
function meinplugin_beim_speichern( $post_id, $post, $update ) {
if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
return;
}
// Eigene Logik nach dem Speichern.
}
Hooks in Klassen verwenden
Größere Plugins organisieren ihren Code in Klassen. Der Callback ist dann ein Array aus Objekt und Methodenname, bei statischen Methoden aus Klassenname und Methodenname:
class Meinplugin_Frontend {
public function __construct() {
add_filter( 'body_class', array( $this, 'klasse_ergaenzen' ) );
add_action( 'init', array( __CLASS__, 'registrieren' ) );
}
public function klasse_ergaenzen( $klassen ) {
$klassen[] = 'meinplugin-aktiv';
return $klassen;
}
public static function registrieren() {
// Inhaltstypen, Shortcodes, Blöcke.
}
}
new Meinplugin_Frontend();
Hängen Sie Hooks nicht im Konstruktor einer Klasse an, die mehrfach instanziert wird, sonst laufen die Funktionen doppelt. Viele Plugins trennen deshalb das Erzeugen eines Objekts vom Registrieren seiner Hooks, etwa über eine eigene Methode, die nur einmal aufgerufen wird. Damit andere Entwickler Ihre Funktionen wieder entfernen können, sollte die Instanz erreichbar bleiben, zum Beispiel über eine globale Variable oder eine statische Methode, die sie zurückgibt.
Action oder Filter: eine Entscheidungshilfe
Wenn Sie selbst einen Hook anbieten oder einen passenden suchen, helfen drei Fragen:
- Soll ein Wert verändert werden, bevor er weiterverwendet oder ausgegeben wird? Dann ist ein Filter richtig.
- Soll an einer Stelle zusätzlicher Code laufen, etwa um etwas zu speichern, zu protokollieren oder auszugeben? Dann ist eine Action richtig.
- Soll ein Verhalten abschaltbar sein? Dann eignet sich ein Filter, der
trueoderfalseliefert, etwaapply_filters( 'meinplugin_hinweis_anzeigen', true ). Diese Technik nutzt WordPress selbst häufig.
Wann welche Hooks feuern
Viele Fehler entstehen, weil Code zu früh läuft. Die grobe Reihenfolge bei einem Seitenaufruf im Frontend:
- plugins_loaded: alle aktiven Plugins sind geladen. Gut, um auf andere Plugins zu prüfen.
- after_setup_theme: das Theme ist geladen, Theme-Funktionen werden registriert.
- init: WordPress ist weitgehend bereit, der Benutzer ist bekannt. Hier registrieren Sie Inhaltstypen, Taxonomien, Shortcodes und Blöcke.
- wp_loaded: alles ist initialisiert.
- template_redirect: die Abfrage steht fest, das passende Template wird gleich geladen. Geeignet für Weiterleitungen.
- wp_head und wp_footer: Ausgabe im Kopf- und Fußbereich der Seite.
Im Adminbereich kommen unter anderem admin_menu für Menüeinträge, admin_init für Einstellungen und admin_enqueue_scripts für Skripte hinzu. Funktionen wie is_singular() oder get_queried_object() liefern erst ab etwa wp beziehungsweise template_redirect sinnvolle Ergebnisse. Wer sie in init aufruft, erhält falsche Werte.
Eigene Hooks anbieten
Ein gutes Plugin nutzt nicht nur Hooks, sondern bietet auch eigene an. So können andere Entwickler und Theme-Autoren Ihr Plugin anpassen, ohne seinen Code zu ändern.
function meinplugin_ausgabe() {
$text = apply_filters( 'meinplugin_text', 'Standardtext' );
do_action( 'meinplugin_vor_ausgabe', $text );
return '<p class="meinplugin">' . esc_html( $text ) . '</p>';
}
Ein anderes Plugin oder die functions.php eines Themes kann nun den Text verändern:
add_filter( 'meinplugin_text', function ( $text ) {
return 'Angepasster Text';
} );
Präfixen Sie auch Hook-Namen, damit sie nicht mit denen anderer Plugins kollidieren, und dokumentieren Sie Parameter und Zweck. Ein einmal veröffentlichter Hook ist eine Schnittstelle, die Sie nicht leichtfertig ändern sollten.
Hooks entfernen
Mit remove_action() und remove_filter() lösen Sie eine Funktion wieder von einem Hook. Das funktioniert nur, wenn Name, Callback und Priorität exakt übereinstimmen:
add_action( 'init', function () {
remove_filter( 'the_content', 'wpautop' );
}, 20 );
Das Beispiel entfernt die automatische Absatzformatierung. Damit das Entfernen greift, muss es nach dem Hinzufügen geschehen. Bei Funktionen anderer Plugins wählen Sie daher einen späten Zeitpunkt wie plugins_loaded oder init mit hoher Priorität. Anonyme Funktionen lassen sich nicht gezielt entfernen, weil es keinen Namen gibt, auf den man sich beziehen könnte.
Nützliche Hilfsfunktionen
has_action()undhas_filter()prüfen, ob etwas an einem Hook hängt.did_action( 'init' )gibt zurück, wie oft eine Action bereits ausgelöst wurde. Nützlich, um zu prüfen, ob Sie zu früh dran sind.current_filter()verrät innerhalb einer Funktion, über welchen Hook sie gerade aufgerufen wurde.doing_action()unddoing_filter()prüfen, ob ein bestimmter Hook gerade läuft.
Typische Fehler und wie Sie sie vermeiden
- Filter ohne Rückgabe: jeder Zweig braucht
return. - Ausgabe in einem Filter per
echo: der Text erscheint an falscher Stelle. Filter geben Werte zurück, sie geben nichts aus. - Zu wenige Argumente angefordert: Ihre Funktion erwartet zwei Parameter,
add_filterfordert aber nur einen an. Das führt zu einem Fehler wegen fehlender Argumente. - Endlosschleifen bei
save_post: Wer insave_postselbstwp_update_post()aufruft, löst den Hook erneut aus. Hängen Sie Ihre Funktion vorher ab und danach wieder an. - Zu früher Zeitpunkt: Code, der den aktuellen Benutzer oder die Abfrage braucht, gehört nicht direkt in die Plugin-Datei, sondern in einen passenden Hook.
Hooks in der Block-Welt
Auch der Block-Editor kennt Hooks, allerdings in JavaScript. Das Paket @wordpress/hooks bietet addFilter() und addAction() nach demselben Prinzip, etwa um Einstellungen bestehender Blöcke zu erweitern. Wer eigene Blöcke baut, findet den Einstieg im Artikel Gutenberg-Block entwickeln mit @wordpress/create-block. Begriffe wie Callback oder Hook erklärt außerdem das Glossar.
Fragen und Antworten
- Was passiert, wenn ein Filter nichts zurückgibt?
- Dann erhält WordPress null statt des ursprünglichen Werts. Beim Filter the_content verschwindet so der gesamte Beitragstext. Jede Filterfunktion muss deshalb in allen Zweigen einen Wert zurückgeben, auch wenn sie ihn gar nicht verändert.
- Welche Priorität sollte ich verwenden?
- Die Standardpriorität 10 passt in den meisten Fällen. Niedrigere Zahlen laufen früher, höhere später. Wählen Sie eine abweichende Priorität nur, wenn Ihre Funktion nachweislich vor oder nach einer bestimmten anderen Funktion laufen muss, etwa 20, um nach Standardfiltern zu arbeiten.
- Warum lässt sich mein remove_action nicht anwenden?
- remove_action und remove_filter brauchen exakt denselben Hook-Namen, dieselbe Funktion und dieselbe Priorität wie beim Hinzufügen. Außerdem muss das Entfernen nach dem Hinzufügen geschehen. Anonyme Funktionen lassen sich praktisch nicht gezielt entfernen, deshalb nutzen erweiterbare Plugins benannte Funktionen oder Methoden.
- Wie finde ich heraus, welche Hooks es gibt?
- Die offizielle Code-Referenz auf developer.wordpress.org listet alle Hooks des Kerns mit Parametern. Im eigenen Projekt helfen eine Volltextsuche nach do_action und apply_filters sowie Debug-Plugins, die anzeigen, welche Hooks bei einem Seitenaufruf ausgelöst werden.
Weiterlesen
- Plugin erstellen
Vom leeren Ordner zum funktionierenden Plugin: Header, Ordnerstruktur, Aktivierungs-Hook, ein Shortcode mit Einstellung und eine saubere uninstall.php.
- Gutenberg-Block
Mit einem Befehl zum lauffähigen Block: was create-block erzeugt, wie block.json, Edit- und Save-Funktion zusammenspielen und wann ein dynamischer Block besser ist.
- Glossar
Von Add-on bis WebExtensions: die wichtigsten Fachbegriffe der Plugin-Entwicklung in kurzen, plattformübergreifenden Erklärungen.