Setiap aplikasi punya pekerjaan rutin: menghapus data lama, mengirim laporan harian, atau mengirim pengingat ke pengguna. Cara lama adalah menambahkan banyak entri cron di server — rumit dan sulit dilacak. Laravel menawarkan pendekatan yang jauh lebih rapi lewat Task Scheduler: Anda mendefinisikan semua jadwal di dalam kode, dan cukup satu entri cron di server. Tutorial ini membahasnya secara tuntas untuk Laravel 10/11.
Bagaimana Scheduler Bekerja
Alih-alih banyak entri cron, Anda menaruh satu cron yang memanggil Laravel setiap menit. Laravel lalu memeriksa jadwal mana yang jatuh tempo saat itu dan menjalankannya. Semua definisi jadwal hidup di dalam aplikasi Anda, sehingga masuk ke version control dan mudah dibaca. Keuntungannya besar: developer baru bisa langsung melihat semua tugas terjadwal hanya dengan membuka satu file kode, tanpa perlu SSH ke server untuk memeriksa crontab yang tersebar.
1. Mendefinisikan Jadwal
Di Laravel 11, jadwal didefinisikan di routes/console.php. Di Laravel 10 dan sebelumnya, gunakan method schedule() pada app/Console/Kernel.php. Contoh sederhana menjalankan closure setiap hari:
use Illuminate\Support\Facades\Schedule;
Schedule::call(function () {
DB::table('sessions')->where('last_activity', '<', now()->subDays(7))->delete();
})->daily();
Anda juga bisa menjadwalkan artisan command yang sudah ada, yang lebih rapi untuk logika kompleks:
Schedule::command('reports:daily')->dailyAt('07:00');
Schedule::command('backup:run')->weekly()->sundays()->at('02:00');
2. Pilihan Frekuensi
Scheduler menyediakan banyak metode frekuensi yang mudah dibaca. Beberapa yang paling sering dipakai:
->everyMinute(); // tiap menit
->everyFiveMinutes(); // tiap 5 menit
->hourly(); // tiap jam
->dailyAt('13:00'); // tiap hari jam 13:00
->weekdays()->at('09:00');// hari kerja jam 09:00
->monthlyOn(1, '00:00'); // tanggal 1 tiap bulan
Anda bahkan bisa membatasi dengan kondisi, misalnya hanya berjalan saat lingkungan produksi:
Schedule::command('newsletter:send')
->dailyAt('08:00')
->when(fn () => app()->environment('production'));
3. Satu Entri Cron di Server
Inilah bagian pentingnya. Di server produksi, tambahkan satu baris cron yang menjalankan scheduler tiap menit. Buka crontab:
crontab -e
Tambahkan baris berikut (sesuaikan path aplikasi Anda):
* * * * * cd /var/www/app && php artisan schedule:run >> /dev/null 2>&1
Selesai. Mulai sekarang, cukup ubah kode untuk menambah atau mengubah jadwal — server tidak perlu disentuh lagi. Untuk menguji tanpa menunggu, jalankan manual:
php artisan schedule:run
Atau jalankan scheduler secara interaktif di lokal tanpa cron:
php artisan schedule:work
4. Tugas Umum yang Cocok Dijadwalkan
- Pembersihan: menghapus log lama, notifikasi kedaluwarsa, atau file sementara.
- Laporan: mengirim ringkasan penjualan harian ke email admin.
- Pengingat: mengirim notifikasi ke pengguna yang tagihannya jatuh tempo.
- Sinkronisasi: menarik data dari API pihak ketiga secara berkala.
Contoh menjadwalkan pembuatan laporan sekaligus mengantrikannya agar tidak memberatkan proses scheduler:
Schedule::job(new GenerateSalesReport)->dailyAt('06:00');
Perhatikan bahwa Schedule::job() tidak menjalankan pekerjaan berat secara langsung di proses scheduler, melainkan menitipkannya ke antrian untuk dikerjakan worker. Ini menjaga scheduler tetap ringan dan cepat, sehingga jadwal lain tidak tertunda hanya karena satu tugas memakan waktu lama.
5. Mencegah Tumpang Tindih (Overlap)
Jika sebuah tugas berjalan lebih lama dari intervalnya, dua instance bisa berjalan bersamaan dan menimbulkan masalah. Cegah dengan withoutOverlapping():
Schedule::command('import:large-file')
->everyMinute()
->withoutOverlapping();
Laravel akan melewati jadwal berikutnya bila instance sebelumnya belum selesai. Jika Anda menjalankan banyak server yang berbagi satu database, gunakan onOneServer() agar tugas hanya dijalankan oleh satu server saja:
Schedule::command('reports:daily')
->dailyAt('07:00')
->onOneServer();
6. Logging Output
Untuk audit dan debugging, arahkan output tugas ke file log. Ini sangat berguna ketika tugas gagal diam-diam:
Schedule::command('backup:run')
->daily()
->appendOutputTo(storage_path('logs/backup.log'));
Anda juga bisa mengirim email saat tugas gagal, atau memanggil URL sebagai sinyal keberhasilan (berguna dengan layanan pemantauan cron):
Schedule::command('backup:run')
->daily()
->emailOutputOnFailure('admin@contoh.com')
->pingOnSuccess('https://monitor.contoh.com/ping');
7. Kesalahan Umum yang Perlu Dihindari
- Lupa entri cron di server: tanpa
schedule:runtiap menit, tidak ada jadwal yang berjalan meski kodenya benar. - Path salah di crontab: gunakan path absolut ke folder aplikasi dan ke binary PHP yang benar.
- Tugas berat menghambat scheduler: bungkus pekerjaan berat sebagai queued job dengan
Schedule::job()agar scheduler tetap ringan.
Dengan menaruh semua jadwal di kode, memakai satu entri cron, mencegah overlap, dan mencatat output, Anda mendapatkan sistem penjadwalan yang rapi, terlacak, dan mudah dirawat — pola yang sama dipakai di hampir semua aplikasi Laravel produksi.
Memantau dan Menguji Penjadwalan
Task scheduling hanya bermanfaat bila benar-benar berjalan sesuai rencana, jadi pemantauan sangat penting. Pastikan satu entri cron di server memicu penjadwal setiap menit, karena inilah fondasi seluruh tugas terjadwal. Catat hasil setiap tugas ke log agar Anda tahu apakah ia berjalan dan berhasil. Untuk tugas kritis, tambahkan notifikasi bila terjadi kegagalan sehingga masalah cepat diketahui. Gunakan penguncian agar tugas yang berdurasi lama tidak tumpang tindih dengan jadwal berikutnya. Saat pengembangan, uji perintah secara manual terlebih dahulu sebelum menyerahkannya ke penjadwal. Dokumentasikan jadwal dan tujuan tiap tugas agar tim memahami apa yang berjalan di latar belakang. Dengan pemantauan, pengujian, dan penanganan kegagalan yang baik, penjadwalan tugas menjadi tulang punggung otomatisasi yang andal untuk aplikasi Anda.
Pertanyaan Umum (FAQ)
Apa syarat utama task scheduling berjalan? Satu entri cron di server yang memicu penjadwal Laravel setiap menit. Tanpa ini, seluruh jadwal tidak akan berjalan.
Bagaimana mencegah tugas tumpang tindih? Gunakan penguncian bawaan agar tugas berdurasi lama tidak dijalankan ulang sebelum eksekusi sebelumnya selesai.
Bisakah menjadwalkan perintah kustom? Bisa. Anda dapat menjadwalkan perintah artisan buatan sendiri maupun closure langsung di dalam penjadwal.