Gereksinimler ve Ön Hazırlık
Bu projeyi hayata geçirmek için sisteminizde PHP 8.2+ ve Laravel 11.x sürümünün yüklü olması gerekmektedir. Ayrıca veritabanı işlemlerini yönetmek için MySQL veya PostgreSQL kullanmanız önerilir. Laravel'in zamanlayıcı yapısı, sunucuda tek bir cron job (zamanlanmış görev) tanımlanmasını gerektirir.
- PHP 8.2 veya üzeri sürüm.
- Composer paket yöneticisi.
- Laravel 11 framework kurulumu.
- Veritabanı bağlantısının yapılandırılmış olması.
Başlamadan önce projenizin .env dosyasında veritabanı bilgilerinizin doğru olduğundan emin olun. Ayrıca, sistemin zamanlayıcıyı tetikleyebilmesi için sunucunuzda * * * * * cd /proje-yolu && php artisan schedule:run >> /dev/null 2>&1 komutunun cron tab üzerinde tanımlı olması şarttır.
Adım 1: Görevleri Saklamak İçin Veritabanı Yapısı
Dinamik bir sistemde görevlerin zamanını, komutunu ve durumunu saklayacak bir tabloya ihtiyacımız vardır. Laravel'in migration (göç) sistemini kullanarak scheduled_tasks tablosunu oluşturalım.
php artisan make:migration create_scheduled_tasks_table
Oluşturulan migration dosyasını aşağıdaki gibi düzenleyerek görevlerin detaylarını tutacak sütunları tanımlayın:
public function up(): void
{
Schema::create('scheduled_tasks', function (Blueprint $table) {
$table->id();
$table->string('name'); // Görev adı
$table->string('command'); // Çalıştırılacak komut veya sınıf
$table->string('expression'); // Cron ifadesi (örn: * * * * *)
$table->boolean('is_active')->default(true); // Görev durumu
$table->timestamps();
});
}
Bu yapı, her bir görevin ne zaman ve hangi komutla çalışacağını veritabanından çekmemize olanak tanır. expression alanı, standart cron formatını (dakika, saat, gün, ay, hafta günü) destekleyecektir.
Adım 2: Dinamik Zamanlayıcıyı Laravel'e Tanımlama
Laravel 11 ile birlikte zamanlayıcı tanımlamaları routes/console.php dosyası üzerinden yapılmaktadır. Dinamik yapıyı kurmak için veritabanındaki aktif görevleri döngüye alıp zamanlayıcıya eklememiz gerekir.
use App\Models\ScheduledTask;
use Illuminate\Support\Facades\Schedule;
// routes/console.php dosyasına ekleyin
ScheduledTask::where('is_active', true)->each(function ($task) {
Schedule::command($task->command)
->cron($task->expression)
->name($task->name);
});
Burada yapılan işlem, uygulama her çalıştığında veritabanındaki aktif görevleri okuyup Laravel'in Schedule nesnesine dinamik olarak enjekte etmektir. Bu sayede kod değişikliği yapmadan yeni görevler ekleyebilirsiniz.
Adım 3: Görevleri Yönetmek İçin Model ve Kontrolcü
Görevlerin yönetimi için bir ScheduledTask modeli ve bu görevleri oluşturup düzenleyeceğimiz bir TaskController oluşturmalıyız. Güvenlik açısından, kullanıcı girişlerini mutlaka doğrulamanız (validation) gerekir.
namespace App\Http\Controllers;
use App\Models\ScheduledTask;
use Illuminate\Http\Request;
class TaskController extends Controller {
public function store(Request $request) {
$validated = $request->validate([
'name' => 'required|string|max:255',
'command' => 'required|string',
'expression' => 'required|string', // Basit bir cron regex eklenebilir
]);
return ScheduledTask::create($validated);
}
}
Bu kontrolcü, kullanıcıdan gelen verileri alır ve veritabanına kaydeder. expression alanı için ileride bir doğrulama kuralı (rule) yazarak kullanıcının geçersiz cron ifadeleri girmesini engelleyebilirsiniz.
Adım 4: Güvenlik ve Hata Yönetimi
Kritik Uyarı: Dinamik olarak komut çalıştırmak, sisteminize sızılması durumunda uzaktan kod çalıştırma (RCE) zafiyetine yol açabilir. Asla kullanıcıdan gelen ham veriyi doğrudanexec()veyasystem()gibi fonksiyonlara göndermeyin. Sadece izin verdiğiniz (whitelist) komutların çalıştırıldığından emin olun.
Görevlerin hata alması durumunda haberdar olmak için Laravel'in onFailure metodunu kullanabilirsiniz. Bu, sistemin izlenebilirliğini artırır.
Schedule::command($task->command)
->cron($task->expression)
->onFailure(function () use ($task) {
// Hata durumunda loglama veya bildirim gönderme
Log::error("Görev başarısız oldu: " . $task->name);
});
Yöntem Karşılaştırması
| Yöntem | Esneklik | Güvenlik | Bakım Kolaylığı |
|---|---|---|---|
| Statik (Kernel/Console) | Düşük | Yüksek | Zor |
| Dinamik (Veritabanı) | Çok Yüksek | Dikkat Gerektirir | Kolay |
Sıkça Sorulan Sorular
Dinamik görevler ne kadar güvenli?
Dinamik görevler, sadece izin verdiğiniz (whitelist) komut sınıflarını çalıştırdığınız sürece güvenlidir. Kullanıcıdan gelen string değerleri doğrudan çalıştırmaktan kaçının.
Cron ifadesini nasıl doğrularım?
dragon-code/cron-expression gibi popüler paketleri kullanarak kullanıcının girdiği cron ifadesinin geçerli olup olmadığını kontrol edebilirsiniz.
Sistem performansı etkilenir mi?
Her istekte veritabanına sorgu atmak yerine, bu görevleri bir cache (önbellek) mekanizmasında tutarak performansı optimize edebilirsiniz.
Geçmiş görevleri nasıl takip ederim?
Her görev çalıştırıldığında bir task_logs tablosuna kayıt atarak çalıştırılma zamanını ve sonucunu kaydedebilirsiniz.
Laravel 11'de zamanlayıcı nerede tanımlanır?
Laravel 11 ile birlikte zamanlayıcı tanımlamaları doğrudan routes/console.php dosyası içerisinde yapılmaktadır.
İleri Seviye İpuçları: Zamanlanmış Görevlerde Performans Optimizasyonu
Dinamik görev zamanlayıcı sistemleri, veritabanı sorgularının sıklığı nedeniyle ölçeklenebilirlik sorunları yaratabilir. Her dakika tüm görevleri veritabanından çekmek yerine, sisteminizi optimize etmek için şu stratejileri izleyebilirsiniz:
- Caching (Önbellekleme): Aktif görevleri her döngüde veritabanından çekmek yerine,
Cachemekanizmasını kullanarak verileri bellekte tutun. Görev güncellendiğinde önbelleği temizlemeyi unutmayın. - Queue (Kuyruk) Kullanımı: Zamanlayıcıyı sadece tetikleyici olarak kullanın. Görev tetiklendiğinde ağır işleri doğrudan çalıştırmak yerine, işi bir kuyruğa (Redis veya SQS) göndererek ana zamanlayıcı döngüsünü serbest bırakın.
// routes/console.php içerisinde kuyruk kullanımı
use App\Models\ScheduledTask;
use Illuminate\Support\Facades\Schedule;
Schedule::call(function () {
$tasks = ScheduledTask::where('is_active', true)->get();
foreach ($tasks as $task) {
// Görevi doğrudan çalıştırmak yerine kuyruğa atıyoruz
dispatch(new \App\Jobs\ExecuteDynamicTask($task));
}
})->everyMinute();
Hata Ayıklama ve İzleme (Monitoring)
Dinamik görevlerin neden çalışmadığını veya neden başarısız olduğunu anlamak için merkezi bir loglama mekanizması şarttır. Laravel'in onFailure ve onSuccess metodlarını kullanarak her görevin çıktısını veritabanına kaydedebilirsiniz.
Görev Başarısızlıklarını Yakalama
Her görevin hata çıktısını yakalamak için modelinizde bir last_error sütunu bulundurmak, sistemin sağlığını izlemenize yardımcı olur:
// routes/console.php içerisinde hata yönetimi
Schedule::call(function () {
try {
// Görev mantığı
} catch (\Exception $e) {
$task->update([
'last_error' => $e->getMessage(),
'status' => 'failed'
]);
}
})->everyMinute()->onFailure(function () {
// Bildirim gönder (Slack, Mail, Telegram)
});
Alternatif: Spatie Laravel-Schedule-Monitor
Kendi sisteminizi yazmak yerine, Laravel topluluğunun standart kabul ettiği spatie/laravel-schedule-monitor paketini kullanabilirsiniz. Bu paket, görevlerin zamanında çalışıp çalışmadığını izlemek ve başarısızlık durumunda uyarı almak için profesyonel bir çözüm sunar.
| Özellik | Özel Sistem | Spatie Paket |
|---|---|---|
| Geliştirme Süresi | Uzun | Kısa |
| Esneklik | Yüksek | Orta |
| Bakım Maliyeti | Yüksek | Düşük |
Eğer uygulamanızda çok sayıda ve karmaşık zamanlanmış görev varsa, hazır paketler üzerinden ilerlemek uzun vadede teknik borç yükünüzü azaltacaktır.
Sonuç
Laravel ile dinamik bir görev zamanlayıcı sistemi kurmak, uygulamanıza büyük bir esneklik kazandırır. Bu rehberde, veritabanı tabanlı bir mimari kurarak görevlerin nasıl yönetileceğini, güvenlik önlemlerini ve hata yönetimini inceledik. Bir sonraki adım olarak, bu görevlerin çalıştırılma loglarını tutan bir raporlama arayüzü geliştirebilir ve görevlerin durumunu gerçek zamanlı olarak izleyebilirsiniz.
Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce mutlaka detaylı güvenlik testlerinden geçirin ve sunucu izinlerini (permission) yapılandırın.


Yorumlar (0)
Yorum Yaz