~/wordpress-plugins/wp-cron/

Geplante Aufgaben im WordPress-Plugin: WP-Cron richtig einsetzen

Termine planen, eigene Intervalle anlegen, beim Deaktivieren aufräumen und wissen, warum WP-Cron von Seitenaufrufen abhängt: so laufen zeitgesteuerte Aufgaben im Plugin zuverlässig.

Mit WP-Cron führt ein Plugin Aufgaben zeitgesteuert aus, ohne dass auf dem Server ein eigener Prozess dauerhaft laufen muss. Typische Beispiele sind regelmäßige Aufräumarbeiten, das Abholen von Daten aus einer Schnittstelle oder wiederkehrende Prüfungen. Damit solche Abläufe zuverlässig und wartbar bleiben, müssen Planung, Ausführung und Fehlerbehandlung zusammenpassen.

Ein Plugin startet solche Aufgaben nicht einfach bei jedem Seitenaufruf. Es plant sie einmalig oder wiederkehrend ein und verbindet dafür einen eigenen Hook mit einer Funktion. Wichtig ist von Anfang an: WP-Cron richtet sich nach Seitenaufrufen, ein Termin wird also nicht zwingend genau zur geplanten Zeit ausgeführt. Das beeinflusst, wie Sie Aufgaben gestalten und überwachen.

So funktioniert WP-Cron

WP-Cron verwaltet die geplanten Ereignisse einer WordPress-Installation. Ein Ereignis besteht unter anderem aus dem Zeitpunkt der nächsten Ausführung, bei wiederkehrenden Aufgaben aus einem Intervall und aus dem Namen eines Hooks. Erkennt WordPress einen fälligen Termin, löst es diesen Hook aus, und die Funktion, die Ihr Plugin daran gehängt hat, läuft. Wie Hooks grundsätzlich funktionieren, erklärt der Artikel WordPress-Hooks: Actions und Filter.

Die wichtigsten Funktionen:

  • wp_schedule_event() plant ein wiederkehrendes Ereignis.
  • wp_schedule_single_event() plant ein einmaliges Ereignis.
  • wp_next_scheduled() prüft, ob für einen Hook schon ein Termin besteht, und liefert dessen Zeitpunkt.
  • wp_unschedule_event() entfernt einen einzelnen Termin anhand von Zeitpunkt und Hook.
  • wp_clear_scheduled_hook() entfernt alle Termine eines Hooks.

Planung und Verarbeitung sind getrennte Schritte. Die Planungsfunktion legt nur fest, wann ein Ereignis fällig wird, die eigentliche Arbeit erledigt die angehängte Funktion. Diese Trennung erleichtert es, Aufgaben einzeln zu prüfen und die Verarbeitung von der Oberfläche des Plugins unabhängig zu halten.

Kein dauerhaft laufender System-Cron

WP-Cron wartet nicht rund um die Uhr im Hintergrund. WordPress prüft bei Seitenaufrufen, ob fällige Ereignisse vorliegen. Auf einer Website mit wenig Besuch läuft eine Aufgabe deshalb womöglich deutlich später als geplant. Bei viel Besuch liegt die Ausführung näher am vorgesehenen Zeitpunkt, minutengenau ist sie aber nie garantiert.

Ein wiederkehrendes Ereignis planen

Das Grundmuster aus dem offiziellen Plugin-Handbuch: Die Funktion hängt an einem eigenen Hook, der Termin wird nur angelegt, wenn es noch keinen gibt. Bei der Deaktivierung räumt das Plugin wieder auf.

add_action( 'meinplugin_aufraeumen', 'meinplugin_aufraeumen_ausfuehren' );

function meinplugin_aufraeumen_ausfuehren() {
    // Eigentliche Arbeit, zum Beispiel veraltete Einträge löschen.
}

register_activation_hook( __FILE__, 'meinplugin_cron_aktivieren' );

function meinplugin_cron_aktivieren() {
    if ( ! wp_next_scheduled( 'meinplugin_aufraeumen' ) ) {
        wp_schedule_event( time(), 'daily', 'meinplugin_aufraeumen' );
    }
}

register_deactivation_hook( __FILE__, 'meinplugin_cron_deaktivieren' );

function meinplugin_cron_deaktivieren() {
    wp_clear_scheduled_hook( 'meinplugin_aufraeumen' );
}

Termine nicht doppelt anlegen

Ein häufiger Fehler ist, denselben wiederkehrenden Termin bei jedem Laden des Plugins neu einzuplanen. Dann entstehen mehrere gleiche Ereignisse, und die Aufgabe läuft öfter als gedacht. Die Prüfung mit wp_next_scheduled() vor dem Planen verhindert das.

Der Hook-Name sollte eindeutig und dauerhaft gleich sein. Ein allgemeiner Name wie aufraeumen kollidiert leicht mit anderen Erweiterungen, ein Präfix wie meinplugin_ macht die Herkunft klar.

Eigene Intervalle

WordPress bringt die Intervalle hourly, twicedaily, daily und weekly mit. Braucht Ihre Aufgabe einen anderen Rhythmus, registrieren Sie ein eigenes Intervall über den Filter cron_schedules:

add_filter( 'cron_schedules', 'meinplugin_intervall' );

function meinplugin_intervall( $schedules ) {
    $schedules['meinplugin_15_minuten'] = array(
        'interval' => 15 * MINUTE_IN_SECONDS,
        'display'  => esc_html__( 'Alle 15 Minuten', 'meinplugin' ),
    );
    return $schedules;
}

Das Intervall beschreibt die gewünschte Wiederholung, nicht den garantierten Ausführungszeitpunkt. Auch ein kurzes Intervall sorgt nicht dafür, dass die Funktion exakt in diesem Takt läuft. Führen Sie ein eigenes Intervall deshalb nur ein, wenn die Aufgabe es wirklich braucht, und geben Sie ihm einen eindeutigen, präfixierten Namen.

Ändern Sie das Intervall in einer neuen Plugin-Version, bleibt ein bereits gespeicherter Termin nach der alten Planung bestehen. In diesem Fall entfernen Sie den alten Termin gezielt und legen ihn neu an.

Einmalige Aufgaben

Für eine Aufgabe, die nur einmal zu einem bestimmten Zeitpunkt laufen soll, ist wp_schedule_single_event() gedacht, etwa für eine Verarbeitung, die nach einer Benutzeraktion etwas später erfolgen soll. Prüfen Sie auch hier vorher, ob für denselben Vorgang schon ein Termin existiert, damit wiederholte Aktionen keine Dubletten erzeugen.

Überlegen Sie außerdem, welche Daten die Funktion später braucht. Statt umfangreiche oder veränderliche Daten als Parameter des Ereignisses zu speichern, übergeben Sie besser eine stabile Kennung, etwa eine Beitrags-ID, und laden die aktuellen Daten erst bei der Ausführung. So verarbeitet die Aufgabe keinen veralteten Stand.

Funktionen kurz, sicher und wiederholbar halten

Eine Cron-Funktion sollte sich auf ihre Aufgabe beschränken. Lange Verarbeitungsschritte belasten den Server und stoßen an Laufzeitgrenzen. Größere Mengen teilen Sie besser in Portionen auf: Ein Lauf erledigt einen Teil und plant bei Bedarf den nächsten Schritt als einmaliges Ereignis ein.

Die Verarbeitung muss außerdem wiederholbar sein. Ein Ereignis kann verspätet laufen oder nach einem Fehler erneut angestoßen werden. Läuft dieselbe Aufgabe zweimal, darf das nicht zu doppelten Einträgen, mehrfachen Benachrichtigungen oder widersprüchlichen Änderungen führen. Speichern Sie deshalb einen nachvollziehbaren Bearbeitungsstand und prüfen Sie vor jeder Aktion, ob sie schon erledigt ist.

Dürfen Aufgaben nicht parallel laufen, braucht es eine Sperre. Sie muss sich nach einem abgebrochenen Lauf wieder lösen, zum Beispiel über eine Ablaufzeit. Eine Sperre, die dauerhaft hängen bleibt, blockiert alle späteren Läufe.

Kein angemeldeter Benutzer, keine ungeprüften Daten

Cron-Ereignisse werden nicht von einer Person im Adminbereich ausgelöst. Ihre Funktion darf also weder einen angemeldeten Benutzer noch eine bestimmte Admin-Seite voraussetzen. Benötigte Daten und Optionen laden Sie ausdrücklich.

Verändert die Aufgabe Inhalte oder Einstellungen, gelten dieselben fachlichen Regeln wie an anderen Stellen des Plugins. Stammen Daten ursprünglich aus einer Anfrage, sind Validierung und Bereinigung Pflicht. Ein geplanter Lauf ist kein Grund, ungeprüfte Werte zu übernehmen.

Aktivierung, Deaktivierung und Updates

Beim Aktivieren legt das Plugin seine Termine an, beim Deaktivieren entfernt es sie, wie im Beispiel oben. Sonst zeigen verwaiste Ereignisse auf einen Hook, an dem keine Funktion mehr hängt. Räumen Sie dabei nur die eigenen Hooks ab, nie allgemeine oder fremde Termine.

Bei der Deinstallation entscheiden Sie bewusst, ob auch gespeicherte Einstellungen und Auftragsdaten verschwinden sollen. Das hängt davon ab, ob sie bei einer späteren Neuinstallation noch gebraucht werden. Dokumentieren Sie in jedem Fall, welche Daten beim Entfernen erhalten bleiben.

Ändern sich bei einem Update Hook-Namen oder Intervalle, muss das Plugin mit den alten Terminen umgehen können. Eine kleine Abgleichroutine prüft, ob die erwartete Planung vorhanden ist, und korrigiert sie nur bei Bedarf. Bei jedem Aufruf alle Termine zu löschen und neu anzulegen, ist dagegen unnötige Arbeit.

Wann ein echter Server-Cronjob besser ist

Muss eine Aufgabe verlässlich zu festen Zeiten laufen, etwa auf einer Website mit wenig Besuch, ist ein Cronjob des Servers die bessere Wahl. Dazu wird WP-Cron in der wp-config.php vom Seitenaufruf abgekoppelt:

define( 'DISABLE_WP_CRON', true );

Anschließend ruft der Server in festen Abständen die Datei wp-cron.php der Website auf, das Plugin-Handbuch nennt dafür zum Beispiel wget. Das ist eine Entscheidung für den Betrieb der Website, keine Einstellung, die ein Plugin selbst erzwingen sollte. Ihr Plugin-Code muss in beiden Fällen mit verspäteten oder wiederholten Ereignissen zurechtkommen.

Fehlersuche bei WP-Cron

Der schnellste Blick auf die geplanten Ereignisse gelingt mit WP-CLI. Der folgende Befehl listet alle Hooks mit ihrem nächsten Termin auf:

wp cron event list --fields=hook,next_run

Fehlt Ihr Hook, wurde der Termin nicht angelegt oder schon entfernt. Taucht er mehrfach auf, fehlt die Prüfung vor dem Planen. In einer lokalen Umgebung mit wp-env führen Sie den Befehl über npx wp-env run cli aus, wie im Artikel Lokale Entwicklungsumgebung mit wp-env beschrieben.

WP-Cron sagt Ihnen außerdem nichts darüber, ob eine Aufgabe fachlich erfolgreich war. Speichern Sie deshalb sinnvolle Zustände oder protokollieren Sie Fehlschläge: wann ein Lauf begonnen hat, ob er abgeschlossen wurde und ob ein weiterer Versuch geplant ist. Zugangsdaten, geheime Schlüssel und unnötige personenbezogene Daten gehören nicht ins Protokoll. Vermeiden Sie auch, bei jedem Seitenaufruf neue Einträge zu erzeugen.

Zu einer robusten Umsetzung gehört schließlich eine Grenze für Wiederholungen. Ein Ereignis, das endlos scheitert, verbraucht Ressourcen und erschwert die Fehlersuche. Erkennt der Code, dass weitere Versuche nicht mehr sinnvoll sind, sollte er aufhören und den Fehler sichtbar machen. Die Logik solcher Aufgaben lässt sich zudem mit automatischen Tests absichern, wie sie der Artikel PHPUnit für WordPress-Plugins beschreibt.

Checkliste für die Umsetzung

  • Für jeden Zweck einen eindeutigen, präfixierten Hook-Namen verwenden.
  • Vor dem Planen prüfen, ob ein Termin schon existiert.
  • Funktionen kurz halten und große Aufgaben portionieren.
  • Wiederholte Ausführung erlauben, ohne Ergebnisse zu verdoppeln.
  • Eigene Ereignisse bei der Deaktivierung gezielt entfernen.
  • Nach Änderungen an Intervallen oder Hooks bestehende Termine abgleichen.
  • Mit Verzögerungen rechnen und keine minutengenaue Ausführung versprechen.
  • Fehler nachvollziehbar festhalten, ohne sensible Daten preiszugeben.

Fazit

WP-Cron eignet sich für zeitgesteuerte Aufgaben in Plugins, solange sie nicht auf die Minute genau laufen müssen. Eine saubere Umsetzung verhindert doppelte Termine, hält die Funktionen kurz und wiederholbar und räumt beim Deaktivieren auf. Wo feste Zeiten zählen, übernimmt ein Cronjob des Servers den Anstoß. Weitere Grundlagen der Plugin-Entwicklung finden Sie in der Übersicht WordPress-Plugins entwickeln.

faq

Fragen und Antworten

Funktioniert WP-Cron auch in einer Multisite?
Ja. Geplante Ereignisse gehören zur jeweiligen Website im Netzwerk. Legen Sie deshalb fest, ob eine Aufgabe für jede einzelne Website gedacht ist oder nur einmal für das gesamte Netzwerk laufen soll. Eine Netzwerkaktivierung macht aus Aufgaben einzelner Websites nicht automatisch eine zentrale Aufgabe.
Läuft ein Cron-Ereignis, während die Website im Wartungsmodus ist?
Das hängt davon ab, wie der Wartungsmodus umgesetzt ist und ob WordPress weiterhin Anfragen verarbeitet. Verlassen Sie sich im Plugin nicht auf ein bestimmtes Verhalten. Für zeitkritische Abläufe stimmen Sie die Serverkonfiguration mit der zuständigen Administration ab.
Wo zeige ich den Status geplanter Aufgaben an?
Das hängt vom Zweck und von der Zielgruppe des Plugins ab. Bei einer wichtigen Hintergrundaufgabe hilft eine kompakte Statusanzeige im passenden Verwaltungsbereich, die Zeitpunkt und Ergebnis des letzten Laufs verständlich nennt. Technische Details sollten dort nicht die eigentliche Bedienung überlagern.