aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Webentwicklung

Laravel Scheduler: Leitfaden für geplante Aufgaben

Mit dem Laravel Scheduler definieren Sie Ihre periodischen Aufgaben direkt im Anwendungscode statt in verstreuten Cron-Zeilen auf dem Server. Arbeiten wie das Erzeugen nächtlicher Berichte, das Bereinigen alter Datensätze, das Aufwärmen des Caches oder das Abrufen von Daten aus einer API planen Sie an einer zentralen Stelle, versioniert, ohne auf jedem Server die crontab von Hand zu bearbeiten. In diesem Artikel gehen wir Schritt für Schritt durch, wie der Scheduler funktioniert, wie Sie Ihre erste Aufgabe definieren, welche Frequenzoptionen es gibt und worauf Sie in der Produktion achten sollten.

Wie der Scheduler funktioniert: eine einzige Cron-Zeile

Im klassischen Ansatz schreiben Sie für jede geplante Aufgabe einen eigenen Cron-Eintrag. Zehn Aufgaben bedeuten zehn Zeilen in der crontab des Servers; sie liegen getrennt von Ihrem Code, tauchen nie in der Versionskontrolle auf und sind mühsam auf einen neuen Server zu übertragen. Laravel dreht das um: Sie fügen nur einen Cron-Eintrag auf dem Server hinzu und verwalten alles Übrige in PHP.

Fügen Sie diese eine Zeile zur crontab des Servers hinzu:

* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

Dieser Eintrag führt jede Minute schedule:run aus. Der Befehl prüft, ob in diesem Moment eine Aufgabe fällig ist; wenn ja, löst er sie aus, andernfalls beendet er sich still. Mit anderen Worten: Cron liefert nur einen „Herzschlag" — die Logik, die entscheidet, welche Aufgabe wann läuft, liegt vollständig auf der Laravel-Seite.

Ihre erste geplante Aufgabe definieren

Ab Laravel 11 (einschließlich Laravel 12) liegen die Planungsdefinitionen in routes/console.php über die Schedule-Fassade. Die alte Datei app/Console/Kernel.php existiert nicht mehr. Das einfachste Beispiel ist der eingebaute inspire-Befehl:

<?php

use Illuminate\Support\Facades\Schedule;

Schedule::command('inspire')->hourly();

Neben dem Ausführen von Befehlen können Sie drei verschiedene Arten von Arbeit planen:

  • Schedule::command('emails:send') — führt einen Artisan-Befehl aus.
  • Schedule::job(new HeavyReport) — stellt einen Job in die Queue.
  • Schedule::call(fn () => DB::table('sessions')->delete()) — führt eine Closure oder ein Callable aus.

Um einen Shell-Befehl auszuführen, können Sie auch Schedule::exec('node /scripts/import.js') verwenden. In den meisten Fällen ist es am saubersten, die Arbeit in einen Artisan-Befehl zu verpacken und diesen zu planen.

Einen eigenen Befehl schreiben

Einen eigenen Artisan-Befehl für eine wiederkehrende Aufgabe zu erstellen, bündelt die Logik an einer Stelle und erlaubt auch das manuelle Ausführen. Erzeugen Sie den Befehl:

php artisan make:command SendDailyReport

Das erstellt app/Console/Commands/SendDailyReport.php. Die $signature definiert den Namen des Befehls und handle() definiert, was er tut:

<?php

namespace App\Console\Commands;

use App\Models\Order;
use Illuminate\Console\Command;

class SendDailyReport extends Command
{
    protected $signature = 'report:daily';
    protected $description = 'Erstellt und versendet den täglichen Verkaufsbericht';

    public function handle(): int
    {
        $total = Order::whereDate('created_at', today())->sum('total');

        $this->info("Heutiger Umsatz: {$total}");
        // ... Bericht per E-Mail senden oder speichern

        return self::SUCCESS;
    }
}

Um den Befehl zu testen, geben Sie einfach php artisan report:daily im Terminal ein. Fügen Sie dann die Planung hinzu:

Schedule::command('report:daily')->dailyAt('07:30');

Frequenzen und Einschränkungen

Der Scheduler bietet eine lesbare, flüssige API. Die am häufigsten verwendeten Frequenzen sind:

  • ->everyMinute(), ->everyFiveMinutes(), ->everyThirtyMinutes()
  • ->hourly(), ->hourlyAt(15) (zur Minute 15 jeder Stunde)
  • ->daily(), ->dailyAt('13:00'), ->twiceDaily(1, 13)
  • ->weekly(), ->monthly(), ->quarterly(), ->yearly()

Sie können diese Frequenzen mit Einschränkungen kombinieren. Zum Beispiel eine Aufgabe, die nur an Wochentagen während der Geschäftszeiten läuft:

Schedule::command('report:daily')
    ->weekdays()
    ->between('9:00', '17:00')
    ->timezone('Europe/Berlin');

Für bedingte Ausführung verwenden Sie ->when(fn () => Feature::active()) oder die Umkehrung ->skip(...). Wenn die Standardfrequenzen nicht ausreichen, können Sie mit ->cron('0 */6 * * *') einen rohen Cron-Ausdruck übergeben. Da sich all diese Methoden verketten lassen, drücken Sie selbst komplexe Pläne in einer einzigen, lesbaren Zeile aus.

Überschneidungen und mehrere Server verwalten

In der Produktion treten zwei wichtige Probleme auf. Das erste ist eine Aufgabe, die erneut startet, bevor ihr vorheriger Lauf beendet ist. Schützen Sie eine lang laufende Aufgabe mit withoutOverlapping():

Schedule::command('report:heavy')
    ->everyFiveMinutes()
    ->withoutOverlapping();

Das zweite tritt auf, wenn Sie dieselbe Anwendung auf mehreren Servern betreiben und jeder Server dieselbe Aufgabe auslöst. Soll eine Aufgabe nur auf einem Server laufen, fügen Sie onOneServer() hinzu (dies erfordert einen Redis- oder Datenbank-Cache-Treiber):

Schedule::command('report:daily')
    ->daily()
    ->onOneServer();

Damit eine Aufgabe die anderen nicht verzögert, können Sie sie mit runInBackground() im Hintergrund ausführen. Sie können sich außerdem mit before(), after(), onSuccess() und onFailure() in den Lebenszyklus der Aufgabe einklinken und die Ausgabe mit emailOutputTo() oder appendOutputTo() umleiten.

Lokal testen und überwachen

Während der Entwicklung gibt es, statt jede Minute auf Cron zu warten, einen Befehl, der im Vordergrund weiterläuft:

php artisan schedule:work

Genau wie Cron auf dem Server wird dieser jede Minute ausgelöst, bleibt aber in Ihrem Terminal — ideal für eine Entwicklungsmaschine. Um alle definierten Aufgaben mit ihren nächsten Ausführungszeiten zu sehen:

php artisan schedule:list

Wenn Sie eine bestimmte Aufgabe sofort ausführen und testen möchten, ohne auf ihre Reihe zu warten, bietet php artisan schedule:test eine interaktive Liste. Mit diesen drei Befehlen beantworten Sie „Warum läuft meine Aufgabe nicht?" in Sekunden statt in Minuten. In der Produktion können Sie, um sicherzugehen, dass Ihre Aufgaben wirklich laufen, einen Überwachungsdienst (etwa einen „Dead Man's Switch") mit thenPing() anpingen.

Häufige Fragen

Was ist der Unterschied zwischen schedule:run und schedule:work?

schedule:run läuft einmalig: Es führt die jetzt fälligen Aufgaben aus und beendet sich; der Cron des Servers ruft es jede Minute auf. schedule:work bleibt als Prozess offen und löst sich intern jede Minute selbst aus. Verwenden Sie Cron + schedule:run in der Produktion und schedule:work lokal.

Sollte ich Cron oder den Laravel Scheduler verwenden?

Beide arbeiten zusammen; der Scheduler ersetzt Cron nicht, sondern reduziert ihn auf eine einzige Zeile. Ihre gesamte Aufgabenlogik bleibt in PHP, in der Versionskontrolle und testbar; auf dem Server verwalten Sie nur einen Cron-Eintrag. Das ist ein enormer Komfort, besonders bei mehreren Aufgaben oder Servern.

Meine geplante Aufgabe läuft nicht — wo fange ich an?

Prüfen Sie zuerst, ob der Cron-Eintrag auf dem Server auf das richtige Verzeichnis und den richtigen PHP-Pfad zeigt. Prüfen Sie dann mit php artisan schedule:list, ob die Aufgabe tatsächlich definiert und zur richtigen Zeit geplant ist. Die meisten Probleme kommen von einer falschen Zeitzone oder einer fehlenden oder fehlerhaften Cron-Zeile.

Möchten Sie Ihre geplanten Aufgaben in Ordnung bringen? Um Ihre verstreuten Cron-Zeilen in einem einzigen Scheduler-Aufbau zusammenzuführen oder neue periodische Jobs einzurichten, kontaktieren Sie mich.

Bu kategorideki tüm yazılar →

Devamı için