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

Laravel Scheduler: Zamanlanmış Görevler Rehberi

Laravel scheduler, periyodik görevlerinizi sunucudaki dağınık cron satırları yerine doğrudan uygulama kodunuzda tanımlamanızı sağlayan bir araçtır. Geceleri rapor üretmek, eski kayıtları temizlemek, önbelleği ısıtmak ya da bir API'den veri çekmek gibi işleri her sunucuda elle crontab düzenlemeden, tek bir merkezi yerde, sürüm kontrolüne dahil ederek planlarsınız. Bu yazıda scheduler'ın nasıl çalıştığını, ilk görevinizi nasıl tanımlayacağınızı, sıklık seçeneklerini ve üretim ortamında dikkat edilmesi gereken noktaları adım adım göreceğiz.

Scheduler nasıl çalışır: tek bir cron satırı

Klasik yaklaşımda her zamanlanmış iş için ayrı bir cron girdisi yazarsınız. On ayrı görev, sunucunun crontab dosyasında on ayrı satır demektir; bunlar koddan kopuktur, sürüm kontrolünde görünmez ve yeni sunucuya taşınmaları zahmetlidir. Laravel bu sorunu tersine çevirir: sunucuya yalnızca tek bir cron girdisi eklersiniz ve geri kalan her şeyi PHP içinde yönetirsiniz.

Sunucunun crontab dosyasına şu tek satırı ekleyin:

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

Bu girdi her dakika schedule:run komutunu çalıştırır. Komut, o an çalışması gereken görev olup olmadığını kontrol eder; varsa onları tetikler, yoksa sessizce çıkar. Yani cron yalnızca bir "kalp atışı" sağlar; hangi işin ne zaman çalışacağına karar veren mantık tamamen Laravel tarafındadır.

İlk zamanlanmış görevinizi tanımlamak

Laravel 11 ve sonrasında (Laravel 12 dahil) zamanlama tanımları routes/console.php dosyasında, Schedule facade'i üzerinden yapılır. Eski sürümlerdeki app/Console/Kernel.php dosyası artık yoktur. En basit örnek hazır gelen inspire komutudur:

<?php

use Illuminate\Support\Facades\Schedule;

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

Komut çalıştırmanın yanı sıra üç farklı şey planlayabilirsiniz:

  • Schedule::command('emails:send') — bir artisan komutunu çalıştırır.
  • Schedule::job(new HeavyReport) — bir kuyruk job'unu kuyruğa atar.
  • Schedule::call(fn () => DB::table('sessions')->delete()) — bir closure ya da çağrılabilir çalıştırır.

Bir shell komutu çalıştırmak için Schedule::exec('node /scripts/import.js') de kullanılabilir. Çoğu durumda en temizi, işi bir artisan komutuna sarmak ve onu planlamaktır.

Kendi komutunuzu yazmak

Tekrar eden bir iş için kendi artisan komutunuzu oluşturmak, hem mantığı tek yerde toplar hem de elle de çalıştırılabilmesini sağlar. Komutu üretin:

php artisan make:command SendDailyReport

Bu, app/Console/Commands/SendDailyReport.php dosyasını oluşturur. $signature komutun adını, handle() ise yapacağı işi tanımlar:

<?php

namespace App\Console\Commands;

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

class SendDailyReport extends Command
{
    protected $signature = 'report:daily';
    protected $description = 'Günlük satış raporunu hazırlar ve gönderir';

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

        $this->info("Bugünkü ciro: {$total}");
        // ... raporu mail at veya kaydet

        return self::SUCCESS;
    }
}

Komutu test etmek için terminalde php artisan report:daily yazmanız yeterli. Ardından zamanlamayı ekleyin:

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

Zamanlama sıklıkları ve kısıtlar

Scheduler, okunması kolay, akıcı bir API sunar. En sık kullanılan sıklıklar şunlardır:

  • ->everyMinute(), ->everyFiveMinutes(), ->everyThirtyMinutes()
  • ->hourly(), ->hourlyAt(15) (her saatin 15. dakikası)
  • ->daily(), ->dailyAt('13:00'), ->twiceDaily(1, 13)
  • ->weekly(), ->monthly(), ->quarterly(), ->yearly()

Bu sıklıkları kısıtlarla birleştirebilirsiniz. Örneğin yalnızca hafta içi, çalışma saatlerinde çalışan bir görev:

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

Bir koşula bağlı çalıştırmak için ->when(fn () => Feature::active()), tersi için ->skip(...) kullanılır. Standart sıklıklar yetmezse ->cron('0 */6 * * *') ile ham bir cron ifadesi de verebilirsiniz. Tüm bu metotlar zincirlenebildiği için karmaşık planlamalar bile tek satırda, okunur biçimde ifade edilir.

Çakışmaları ve birden fazla sunucuyu yönetmek

Üretim ortamında iki önemli sorun çıkar. İlki, bir görevin bir önceki çalışması bitmeden yenisinin başlamasıdır. Uzun süren bir görevi withoutOverlapping() ile koruyun:

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

İkincisi, aynı uygulamayı birden çok sunucuda çalıştırdığınızda her sunucunun aynı görevi tetiklemesidir. Görevin yalnızca tek bir sunucuda çalışmasını istiyorsanız onOneServer() ekleyin (bunun için Redis ya da database önbellek sürücüsü gerekir):

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

Bir görevin diğerlerini bekletmemesi için onu arka planda çalıştırmak isteyebilirsiniz: runInBackground(). Ayrıca before(), after(), onSuccess() ve onFailure() kancalarıyla görev yaşam döngüsüne bağlanabilir; emailOutputTo() ya da appendOutputTo() ile çıktıyı yönlendirebilirsiniz.

Yerelde test etmek ve izlemek

Geliştirme sırasında her dakika cron beklemeden zamanlayıcıyı çalıştırmak için, ön planda sürekli çalışan bir komut vardır:

php artisan schedule:work

Bu komut, tıpkı sunucudaki cron gibi her dakika tetiklenir ama terminalinizde durur; geliştirme makinesi için idealdir. Tanımlı tüm görevleri, sonraki çalışma zamanlarıyla birlikte görmek için:

php artisan schedule:list

Belirli bir görevi anında, sırasını beklemeden çalıştırıp test etmek isterseniz php artisan schedule:test komutu interaktif bir liste sunar. Bu üç komut, "görevim neden çalışmıyor?" sorusunun cevabını dakikalar yerine saniyeler içinde bulmanızı sağlar. Üretimde ise görevlerin gerçekten çalıştığından emin olmak için bir izleme servisine (örneğin bir "dead man's switch") thenPing() ile haber gönderebilirsiniz.

Sık Sorulan Sorular

schedule:run ile schedule:work arasındaki fark nedir?

schedule:run tek seferlik çalışır: o anda vadesi gelen görevleri çalıştırıp çıkar; sunucudaki cron bunu her dakika çağırır. schedule:work ise süreç olarak açık kalır ve içeride her dakika kendini tetikler. Üretimde cron + schedule:run, yerelde ise schedule:work kullanın.

Cron mu yoksa Laravel scheduler mı kullanmalıyım?

İkisi birlikte çalışır; scheduler cron'un yerini almaz, onu tek bir satıra indirir. Tüm görev mantığınız PHP'de, sürüm kontrolünde ve test edilebilir olur; sunucuda yalnızca tek bir cron girdisini yönetirsiniz. Bu, özellikle birden fazla görev veya sunucu olduğunda büyük kolaylıktır.

Zamanlanmış görevim çalışmıyor, nereden başlamalıyım?

Önce sunucudaki cron girdisinin doğru dizini ve PHP yolunu gösterdiğini doğrulayın. Sonra php artisan schedule:list ile görevin gerçekten tanımlı ve doğru saatte planlı olduğunu kontrol edin. Çoğu sorun, yanlış zaman dilimi ya da eksik/yanlış cron satırından kaynaklanır.

Zamanlanmış görevlerinizi düzene sokmak ister misiniz? Dağınık cron satırlarınızı tek bir scheduler yapısında toplamak veya yeni periyodik işler kurmak için benimle iletişime geçin.

Bu kategorideki tüm yazılar →

Devamı için