در بسیاری از پروژههای واقعی، بعضی عملیاتها نباید توسط کاربر و بهصورت دستی اجرا شوند.
برای مثال ممکن است بخواهیم:
- هر روز گزارش فروش ایجاد شود.
- هر ساعت اطلاعاتی از یک API دریافت شود.
- هر شب دادههای قدیمی پاک شوند.
- هر دقیقه وضعیت یک سرویس بررسی شود.
- هر هفته یک گزارش برای مدیر ارسال شود.
- Subscriptionهای منقضیشده بررسی شوند.
- Cacheهای خاصی بازسازی شوند.
- Jobهای مشخصی در زمان معین اجرا شوند.
برای انجام این کارها در Laravel میتوان از Task Scheduling استفاده کرد.
Task Scheduling یا Scheduler لاراول به ما اجازه میدهد اجرای Commandها، Jobها، Closureها و بعضی عملیات دیگر را طبق یک برنامه زمانی مشخص مدیریت کنیم.
در این مقاله از مفهوم Scheduler شروع میکنیم و سپس نحوه تعریف Schedule، اتصال آن به Cron، اجرای schedule:run و schedule:work، زمانبندی Command و Job و نکات مهم Production را بررسی میکنیم.
# Task Scheduling در Laravel چیست؟
Task Scheduling سیستمی در Laravel برای زمانبندی اجرای خودکار وظایف است.
به جای اینکه برای هر عملیات یک Cron Job جداگانه در سرور ایجاد کنیم، میتوانیم زمانبندی وظایف را داخل خود پروژه Laravel تعریف کنیم.
برای مثال:
Schedule::command('reports:daily')->daily();
این کد به Laravel میگوید:
> Command مربوط به reports:daily را روزانه اجرا کن.
یا:
Schedule::call(function () {
// عملیات موردنظر
})->hourly();
یعنی Closure موردنظر را هر ساعت اجرا کن.
در نتیجه Laravel تبدیل به مرکزی برای مدیریت Taskهای زمانبندیشده پروژه میشود.
# چرا از Laravel Scheduler استفاده کنیم؟
بدون Scheduler ممکن است مجبور شویم تعداد زیادی Cron Job روی سرور تعریف کنیم.
مثلاً:
Cron 1 → پاک کردن سفارشهای موقت
Cron 2 → ارسال گزارش
Cron 3 → بررسی Subscription
Cron 4 → دریافت نرخ ارز
Cron 5 → پاک کردن فایلهای قدیمی
اما با Laravel Scheduler میتوانیم همه این زمانبندیها را در Application مدیریت کنیم:
Laravel Scheduler
│
┌───────────────┼───────────────┐
↓ ↓ ↓
Command Job Closure
↓ ↓ ↓
Daily Hourly Weekly
این روش باعث میشود منطق زمانبندی داخل خود پروژه قرار بگیرد و مدیریت آن سادهتر شود.
# تفاوت Scheduler با Cron چیست؟
این دو مفهوم یکی نیستند.
Cron
Cron یک سیستم زمانبندی در سطح سیستمعامل است.
مثلاً روی Linux میتوان یک Cron Job تعریف کرد:
* * * * * cd /var/www/example && php artisan schedule:run >> /dev/null 2>&1
Laravel Scheduler
Scheduler سیستم زمانبندی داخلی Laravel است.
مثلاً:
Schedule::command('reports:daily')->daily();
در این معماری:
Linux Cron
↓
schedule:run
↓
Laravel Scheduler
↓
بررسی Taskها
↓
اجرای Taskهای موعددار
بنابراین Cron و Laravel Scheduler رقیب یکدیگر نیستند.
Cron معمولاً مسئول بیدار کردن Scheduler است و Laravel مسئول مدیریت زمانبندی Taskهای Application است.
# Laravel Scheduler در کجا قرار دارد؟
در نسخههای جدید Laravel، تعریف Schedule معمولاً در:
routes/console.php
انجام میشود.
برای مثال:
use Illuminate\Support\Facades\Schedule;
Schedule::call(function () {
// عملیات
})->daily();
این موضوع با ساختار نسخههای قدیمی Laravel متفاوت است؛ بنابراین اگر آموزشهای قدیمی اینترنت را میخوانید، ممکن است محل تعریف Scheduler متفاوت باشد.
در پروژههای جدید بهتر است ساختار فعلی پروژه خود را مبنا قرار دهید.
# اولین Task زمانبندیشده در Laravel
فرض کنیم میخواهیم یک عملیات را هر روز اجرا کنیم.
در routes/console.php:
use Illuminate\Support\Facades\Schedule;
Schedule::call(function () {
\Log::info('Daily task executed.');
})->daily();
اکنون Laravel این Task را بهعنوان یک عملیات روزانه میشناسد.
اما هنوز یک نکته مهم وجود دارد:
Laravel خودش بدون Scheduler Trigger خارجی، زمانبندی را اجرا نمیکند.
برای اجرای Scheduler باید آن را از طریق Cron یا فرآیند مناسب دیگری اجرا کنیم.
# schedule:run چیست؟
یکی از مهمترین دستورات Scheduler این دستور است:
php artisan schedule:run
این دستور Scheduleهای Laravel را بررسی میکند و Taskهایی را که زمان اجرای آنها رسیده است، اجرا میکند.
مثلاً:
php artisan schedule:run
Laravel بررسی میکند:
Task A → موعدش رسیده؟
Task B → موعدش رسیده؟
Task C → موعدش رسیده؟
Task D → هنوز زود است؟
و فقط Taskهای لازم را اجرا میکند.
# Cron برای Laravel Scheduler
در Production معمولاً یک Cron Job برای اجرای Scheduler تعریف میشود.
نمونه:
* * * * * cd /var/www/example && php artisan schedule:run >> /dev/null 2>&1
در اینجا:
* * * * *
یعنی Cron هر دقیقه اجرا شود.
سپس:
php artisan schedule:run
Scheduler Laravel را اجرا میکند.
در نتیجه:
هر دقیقه
↓
Cron
↓
schedule:run
↓
Laravel
↓
بررسی Scheduleها
↓
اجرای Taskهای موعددار
این یکی از مهمترین بخشهای راهاندازی Scheduler در Production است.
# چگونه Cron را برای Laravel تنظیم کنیم؟
روی Ubuntu یا سایر Linuxهای دارای Cron میتوانید Cron را با دستور زیر باز کنید:
crontab -e
سپس این خط را اضافه کنید:
* * * * * cd /var/www/example && php artisan schedule:run >> /dev/null 2>&1
البته مسیر:
/var/www/example
باید با مسیر واقعی پروژه Laravel شما جایگزین شود.
مثلاً اگر پروژه در:
/home/example.com/public_html
باشد:
* * * * * cd /home/example.com/public_html && php artisan schedule:run >> /dev/null 2>&1
# چرا Cron را هر دقیقه اجرا میکنیم؟
ممکن است بپرسید اگر Task ما روزانه است، چرا Cron را هر دقیقه اجرا کنیم؟
چون Cron وظیفه ندارد مستقیماً Task روزانه را اجرا کند.
وظیفه آن این است که Scheduler Laravel را مرتب بررسی کند.
مثلاً:
Schedule::command('reports:daily')->dailyAt('02:00');
Cron هر دقیقه Laravel را اجرا میکند و Laravel بررسی میکند که آیا ساعت به 02:00 رسیده است یا خیر.
اگر نرسیده باشد:
Nothing to run
و اگر رسیده باشد:
Run reports:daily
# schedule:work چیست؟
Laravel علاوه بر schedule:run، دستور دیگری نیز برای اجرای Scheduler دارد:
php artisan schedule:work
این دستور Scheduler را بهصورت مداوم در حال اجرا نگه میدارد و برای محیطهایی که میخواهید Scheduler بهصورت دائمی در حال کار باشد، کاربرد دارد.
در محیط Development میتوانید برای تست Scheduler از آن استفاده کنید:
php artisan schedule:work
سپس Terminal را باز نگه دارید و منتظر اجرای Task باشید.
این روش برای تست زمانبندی بسیار راحت است.
# schedule:run یا schedule:work؟
بهصورت ساده:
| دستور | کاربرد |
|---|---|
schedule:run | اجرای یکباره بررسی Scheduler |
schedule:work | اجرای مداوم Scheduler |
در Production معمولاً میتوانید Scheduler را با Cron و schedule:run مدیریت کنید.
در برخی معماریها نیز اجرای دائمی schedule:work میتواند گزینه مناسبی باشد.
انتخاب روش باید با معماری Deployment پروژه شما هماهنگ باشد.
# زمانبندی Command در Laravel
یکی از بهترین کاربردهای Scheduler، اجرای Artisan Command است.
فرض کنید Command زیر را ساختهایم:
php artisan make:command GenerateDailyReport
بعد از پیادهسازی Command میتوانیم آن را زمانبندی کنیم:
Schedule::command('report:generate')->daily();
یا مثلاً:
Schedule::command('report:generate')->hourly();
در این حالت Laravel اجرای Command را مدیریت میکند.
# زمانبندی Job در Laravel
Scheduler فقط مخصوص Command نیست.
میتوان Jobها را نیز زمانبندی کرد.
مثلاً:
Schedule::job(new GenerateReport)->daily();
در این حالت Laravel Job را طبق Schedule موردنظر Dispatch میکند.
اگر Queue نیز تنظیم شده باشد، Job میتواند برای پردازش پسزمینه وارد Queue شود.
معماری میتواند به شکل زیر باشد:
Scheduler
↓
Dispatch Job
↓
Queue
↓
Worker
↓
Process
این ترکیب در پروژههای بزرگ Laravel بسیار کاربردی است.
# ترکیب Scheduler و Queue
فرض کنید هر شب باید گزارش فروش تولید شود.
اگر تولید گزارش سنگین باشد، بهتر است Scheduler مستقیماً عملیات سنگین را انجام ندهد.
بهتر است:
Scheduler
↓
Dispatch Job
↓
Redis / Queue
↓
Worker
↓
Generate Report
مثلاً:
Schedule::job(new GenerateDailySalesReport)->dailyAt('01:00');
در این معماری Scheduler فقط Job را وارد Queue میکند و Worker عملیات سنگین را انجام میدهد.
این روش برای پروژههای بزرگ بسیار مناسبتر است.
# زمانبندی Closure
میتوان یک Closure را نیز زمانبندی کرد:
Schedule::call(function () {
// عملیات موردنظر
})->daily();
برای عملیاتهای کوچک این روش ساده و کاربردی است.
اما اگر عملیات پیچیده شود، معمولاً بهتر است منطق را به:
- Command
- Job
- Service
منتقل کنیم.
# زمانبندی در هر دقیقه
برای اجرای Task در هر دقیقه:
Schedule::call(function () {
// Task
})->everyMinute();
این یکی از سادهترین Intervalها در Scheduler است.
# اجرای Task هر پنج دقیقه
Schedule::call(function () {
// Task
})->everyFiveMinutes();
مثلاً میتوان برای بررسی وضعیت سرویسها استفاده کرد.
# اجرای Task هر ده دقیقه
Schedule::call(function () {
// Task
})->everyTenMinutes();
# اجرای Task هر پانزده دقیقه
Schedule::call(function () {
// Task
})->everyFifteenMinutes();
# اجرای Task هر سی دقیقه
Schedule::call(function () {
// Task
})->everyThirtyMinutes();
# اجرای Task هر ساعت
Schedule::call(function () {
// Task
})->hourly();
# اجرای Task روزانه
Schedule::call(function () {
// Task
})->daily();
این Task بهصورت روزانه اجرا میشود.
# اجرای Task در ساعت مشخص
اگر بخواهیم Task هر روز در ساعت مشخصی اجرا شود:
Schedule::call(function () {
// Generate report
})->dailyAt('02:00');
یعنی:
هر روز ساعت 02:00
# اجرای Task هفتگی
برای اجرای هفتگی:
Schedule::call(function () {
// Weekly task
})->weekly();
# اجرای Task ماهانه
برای اجرای ماهانه:
Schedule::call(function () {
// Monthly task
})->monthly();
# اجرای Task در روز خاص
میتوان زمانبندی را دقیقتر کرد.
مثلاً:
Schedule::call(function () {
// Weekly report
})->weeklyOn(1, '08:00');
در اینجا میتوان روز و ساعت اجرای Task را مشخص کرد.
# زمانبندی با Cron Expression
Laravel امکان استفاده از Cron Expression را نیز فراهم میکند.
مثلاً:
Schedule::command('report:generate')
->cron('0 2 * * *');
این Expression یعنی Task در ساعت 2 بامداد اجرا شود.
Cron Expression برای زمانبندیهای پیچیدهتر بسیار قدرتمند است.
اما برای زمانبندیهای معمول، متدهای خواناتر Laravel معمولاً انتخاب بهتری هستند:
->dailyAt('02:00')
بهجای:
->cron('0 2 * * *')
# timezone در Laravel Scheduler
زمانبندیها باید با Timezone موردنظر Application هماهنگ باشند.
فرض کنید:
Schedule::command('report:generate')
->dailyAt('02:00');
اگر Timezone پروژه با Timezone موردنظر شما متفاوت باشد، Task ممکن است در ساعت اشتباه اجرا شود.
بنابراین در پروژههای بینالمللی باید Timezone را جدی بگیرید.
این موضوع مخصوصاً برای سیستمهایی که کاربران آنها در کشورهای مختلف هستند اهمیت زیادی دارد.
# جلوگیری از اجرای همزمان Task
گاهی ممکن است یک Task هنوز تمام نشده باشد ولی زمان اجرای بعدی آن فرا برسد.
مثلاً Task هر دقیقه اجرا میشود:
Schedule::command('sync:services')->everyMinute();
اما اجرای آن 3 دقیقه طول میکشد.
ممکن است در شرایط نامناسب چند نسخه همزمان اجرا شوند.
برای چنین سناریوهایی میتوان از قابلیت جلوگیری از اجرای همزمان استفاده کرد:
Schedule::command('sync:services')
->everyMinute()
->withoutOverlapping();
در این حالت Laravel تلاش میکند تا زمانی که اجرای قبلی تمام نشده، اجرای بعدی را شروع نکند.
این قابلیت برای Taskهای طولانی بسیار مهم است.
# بدون Overlap چه مشکلی ایجاد میشود؟
فرض کنید:
00:00 → Task Start
00:01 → Task Start
00:02 → Task Start
00:03 → Task Start
اگر Task سه دقیقه طول بکشد، ممکن است چند نسخه همزمان فعال شوند.
برای عملیاتی مانند:
- Synchronization
- Import
- پردازش سفارش
- تولید گزارش
- دریافت اطلاعات API
این وضعیت میتواند مشکلساز شود.
با:
->withoutOverlapping()
میتوان این ریسک را کاهش داد.
# اجرای Task فقط روی یک سرور
اگر Application شما روی چند Server اجرا شود:
Server 1
Server 2
Server 3
و Scheduler روی هر سه Server اجرا شود، ممکن است یک Task سه بار اجرا شود.
در چنین شرایطی میتوان از قابلیت اجرای Task روی یک Server استفاده کرد:
Schedule::command('report:generate')
->daily()
->onOneServer();
این قابلیت برای معماریهای Multi-Server اهمیت زیادی دارد.
البته استفاده صحیح از آن نیازمند تنظیم Cache Store مشترک بین Serverها است.
# اجرای Task فقط در محیط Production
گاهی یک Task نباید در محیط Development اجرا شود.
میتوان اجرای آن را به Environment مشخص محدود کرد:
Schedule::command('report:generate')
->daily()
->environments(['production']);
در نتیجه این Task فقط در Environment موردنظر اجرا خواهد شد.
این قابلیت برای جلوگیری از اجرای اشتباه Taskهای حساس در محیط Development بسیار مفید است.
# شرطگذاری روی Taskها
گاهی نمیخواهیم Task همیشه اجرا شود.
مثلاً فقط زمانی اجرا شود که شرایط خاصی برقرار باشد.
میتوان از شرط استفاده کرد:
Schedule::command('report:generate')
->daily()
->when(function () {
return true;
});
همچنین میتوان شرایطی برای جلوگیری از اجرا تعریف کرد.
این قابلیت برای Scheduleهای پیچیدهتر کاربرد دارد.
# اجرای Task در شرایط خاص
فرض کنید یک سرویس فقط زمانی باید Billing شود که استفادهای در آن روز ثبت شده باشد.
میتوان منطق شرط را در Scheduler یا Command مربوطه قرار داد.
برای مثال:
Schedule::command('billing:process')
->daily()
->when(fn () => /* condition */);
اما برای منطق تجاری پیچیده بهتر است Condition اصلی داخل Service یا Command قرار گیرد و Scheduler فقط مسئول زمانبندی باشد.
# مدیریت خروجی Command
گاهی میخواهیم خروجی Command زمانبندیشده در فایل ذخیره شود.
برای مثال:
Schedule::command('report:generate')
->daily()
->appendOutputTo(storage_path('logs/report.log'));
این قابلیت برای Debug و بررسی اجرای Taskها میتواند مفید باشد.
# ثبت خروجی و Debug کردن Scheduler
یکی از مشکلات رایج این است که Task اجرا نمیشود و مشخص نیست مشکل کجاست.
برای Debug ابتدا میتوان Command را دستی اجرا کرد:
php artisan report:generate
اگر Command دستی اجرا نشود، مشکل احتمالاً مربوط به خود Command است، نه Scheduler.
بعد Scheduler را بررسی کنید:
php artisan schedule:run
و در صورت نیاز Logهای Laravel را بررسی کنید.
# لیست Taskهای زمانبندیشده
برای بررسی Scheduleهای تعریفشده میتوان از Artisan استفاده کرد:
php artisan schedule:list
این دستور برای Debug کردن Scheduler بسیار مفید است.
با استفاده از آن میتوانید ببینید چه Taskهایی تعریف شدهاند و زمانبندی آنها چیست.
# Task Scheduling و Cron در Production
یک معماری معمول Production به شکل زیر است:
Linux Cron
│
│ Every Minute
↓
php artisan schedule:run
↓
Laravel Scheduler
│
├── Daily Command
├── Hourly Job
├── Every 5 Minutes
└── Weekly Report
این ساختار ساده، قابل مدیریت و بسیار رایج است.
# Task Scheduling و Queue چه تفاوتی دارند؟
این دو مفهوم را نباید با هم اشتباه گرفت.
Scheduler
مشخص میکند:
> چه زمانی یک Task اجرا شود؟
Queue
مشخص میکند:
> یک Job چگونه در پسزمینه پردازش شود؟
مثلاً:
Scheduler
↓
هر روز ساعت 01:00
↓
Dispatch Job
↓
Queue
↓
Worker
↓
Execute
در این معماری هر کدام وظیفه مشخصی دارند.
# Scheduler جایگزین Queue نیست
فرض کنید یک گزارش بسیار سنگین داریم.
اشتباه:
Scheduler
↓
Generate huge report
بهتر:
Scheduler
↓
Dispatch Job
↓
Queue
↓
Worker
↓
Generate report
Scheduler برای زمانبندی مناسب است و Queue برای پردازشهای پسزمینه.
# Scheduler و Redis
Redis میتواند در معماری Scheduler نیز نقش داشته باشد؛ مخصوصاً زمانی که از Queue یا Cache مشترک استفاده میکنیم.
مثلاً:
Scheduler
↓
Job
↓
Redis Queue
↓
Worker
در این حالت Scheduler شروعکننده فرآیند است و Redis و Queue وظیفه انتقال و پردازش Job را بر عهده دارند.
# مثال واقعی: بررسی سرویسهای منقضیشده
فرض کنید یک SaaS داریم و باید هر روز Subscriptionهای منقضیشده بررسی شوند.
میتوانیم یک Command داشته باشیم:
php artisan make:command ProcessExpiredSubscriptions
سپس آن را روزانه اجرا کنیم:
Schedule::command('subscriptions:process-expired')
->dailyAt('00:30');
معماری:
00:30
↓
Laravel Scheduler
↓
subscriptions:process-expired
↓
Find expired subscriptions
↓
Update status
↓
Send notification
اگر عملیات سنگین باشد، بهتر است Command به جای پردازش مستقیم، Jobهای موردنیاز را Dispatch کند.
# مثال واقعی: دریافت نرخ ارز
فرض کنید سیستم شما هر 10 دقیقه باید نرخ ارز را از یک API دریافت کند.
میتوانیم داشته باشیم:
Schedule::job(new UpdateCurrencyRates)
->everyTenMinutes();
و معماری:
Every 10 Minutes
↓
Scheduler
↓
UpdateCurrencyRates
↓
Queue
↓
Worker
↓
External API
↓
Database / Cache
این مدل برای پروژههایی که با APIهای خارجی کار میکنند بسیار کاربردی است.
# مثال واقعی: پاکسازی دادههای قدیمی
فرض کنید Log یا دادههای موقتی زیادی در Database ایجاد میشوند.
میتوان یک Command ساخت:
php artisan make:command CleanupOldData
و آن را زمانبندی کرد:
Schedule::command('data:cleanup')
->dailyAt('03:00');
در نتیجه سیستم بدون دخالت کاربر دادههای قدیمی را پاک میکند.
# مثال واقعی: ارسال گزارش روزانه
فرض کنید هر روز صبح مدیر باید گزارش فروش دریافت کند.
میتوان:
Schedule::job(new SendDailySalesReport)
->dailyAt('08:00');
استفاده کرد.
اگر Mail نیز در Queue قرار بگیرد:
Scheduler
↓
Job
↓
Queue
↓
Mail
این روش باعث میشود Scheduler درگیر ارسال مستقیم Email نشود.
# نکات مهم برای Taskهای حساس
برای Taskهایی که عملیات مالی یا حساس انجام میدهند باید دقت بیشتری داشته باشید.
مثلاً:
پرداخت
Billing
شارژ کیف پول
تمدید اشتراک
تغییر موجودی
نباید فقط به Scheduler اعتماد کنید.
منطق Application باید در برابر اجرای تکراری نیز مقاوم باشد.
یعنی حتی اگر Task به هر دلیلی دوبار اجرا شد، نباید عملیات مالی دوبار انجام شود.
برای چنین سیستمهایی باید از مواردی مانند:
- Unique Constraint
- Transaction
- Lock
- Idempotency
withoutOverlapping()
در جای مناسب استفاده کرد.
# Idempotency در Task Scheduling
فرض کنید Task زیر اجرا میشود:
Process Payment
اگر به هر دلیلی دو بار اجرا شود، نباید دو پرداخت ثبت شود.
پس بهتر است منطق Command یا Job به شکلی طراحی شود که اجرای مجدد آن نتیجه مخرب ایجاد نکند.
مثلاً قبل از انجام عملیات، وضعیت Transaction بررسی شود:
if ($transaction->isCompleted()) {
return;
}
Scheduler فقط زمان اجرا را کنترل میکند.
امنیت و صحت عملیات باید داخل Business Logic نیز کنترل شود.
# جلوگیری از اجرای چندباره Cron
یکی از مشکلات رایج در سرور این است که یک Cron Job چند بار تعریف شده باشد.
مثلاً:
* * * * * php artisan schedule:run
* * * * * php artisan schedule:run
در چنین شرایطی ممکن است Scheduler چند بار در هر دقیقه اجرا شود.
بنابراین همیشه Cronهای سرور را بررسی کنید:
crontab -l
و مطمئن شوید Scheduler فقط بهشکل موردنظر تعریف شده است.
# مشکلات رایج Laravel Scheduler
Task اجرا نمیشود
ابتدا:
php artisan schedule:list
را بررسی کنید.
سپس:
php artisan schedule:run
را بهصورت دستی اجرا کنید.
Cron اجرا نمیشود
Cron را بررسی کنید:
crontab -l
و مطمئن شوید مسیر پروژه و PHP صحیح هستند.
مثلاً در بعضی سرورها php ممکن است به نسخه متفاوتی اشاره کند.
برای بررسی:
which php
php -v
مسیر پروژه اشتباه است
در Cron باید مسیر واقعی Laravel مشخص باشد:
* * * * * cd /path/to/laravel && php artisan schedule:run
اگر مسیر اشتباه باشد، Scheduler اجرا نمیشود.
Permission مشکل دارد
کاربری که Cron را اجرا میکند باید دسترسی لازم به پروژه و Storage را داشته باشد.
این موضوع مخصوصاً در سرورهای Production مهم است.
Task اجرا میشود اما Job پردازش نمیشود
اگر Scheduler یک Job را Dispatch کند ولی Queue Worker فعال نباشد:
Scheduler
↓
Job
↓
Queue
↓
❌ Worker
Job ممکن است در Queue باقی بماند.
پس در چنین معماریای باید Scheduler و Queue Worker را جداگانه بررسی کنید.
# چکلیست راهاندازی Scheduler در Production
قبل از Deploy، این موارد را بررسی کنید:
1. Schedule تعریف شده است؟
php artisan schedule:list
2. Command دستی اجرا میشود؟
php artisan your:command
3. Scheduler دستی اجرا میشود؟
php artisan schedule:run
4. Cron وجود دارد؟
crontab -l
5. PHP صحیح استفاده میشود؟
php -v
6. مسیر پروژه صحیح است؟
/path/to/project
7. Permissionها صحیح هستند؟
8. اگر Job استفاده شده، Queue Worker فعال است؟
php artisan queue:work
# ساختار پیشنهادی برای پروژههای حرفهای
در پروژههای بزرگ بهتر است Scheduler را تبدیل به محل نگهداری منطق تجاری نکنیم.
مثلاً این کار مناسب نیست:
Schedule::call(function () {
// صدها خط Business Logic
})->daily();
بهتر است:
Scheduler
↓
Command / Job
↓
Service
↓
Business Logic
مثلاً:
Schedule::command('billing:process')
->daily();
و Business Logic داخل Command و Service قرار داشته باشد.
این ساختار باعث میشود:
- تست آسانتر شود
- کد خواناتر باشد
- Command قابل اجرای دستی باشد
- Business Logic از Scheduler جدا بماند
# بهترین روش برای نامگذاری Taskها
نامگذاری واضح بسیار مهم است.
به جای:
task1
task2
process
run
از نامهای مشخص استفاده کنید:
billing:process-due
subscriptions:renew
reports:generate-daily
services:sync-status
notifications:send-reminders
data:cleanup
این کار در پروژههای بزرگ Debug کردن Scheduler را بسیار سادهتر میکند.
# Task Scheduling و پروژههای SaaS
در پروژههای SaaS معمولاً Scheduler کاربرد بسیار زیادی دارد.
مثلاً:
هر دقیقه:
بررسی وضعیت Jobها
هر 10 دقیقه:
همگامسازی اطلاعات
هر ساعت:
بررسی سرویسها
هر روز:
Billing
هر هفته:
گزارش
هر ماه:
Invoice
یک ساختار واقعی میتواند اینگونه باشد:
Laravel Scheduler
│
├── Services Sync
├── Billing
├── Notifications
├── Reports
├── Cleanup
└── Renewals
در پروژههای بزرگتر بهتر است هر عملیات مهم به Command یا Job مستقل منتقل شود.
# جمعبندی
Task Scheduling یکی از قابلیتهای مهم Laravel برای مدیریت عملیاتهای دورهای است.
با Scheduler میتوانیم اجرای مواردی مانند:
- Artisan Command
- Job
- Closure
- گزارشها
- Cleanup
- Synchronization
- Notification
- Billing
- دریافت اطلاعات API
را زمانبندی کنیم.
مهمترین مفهومی که باید به خاطر داشته باشید این است:
Cron
↓
schedule:run
↓
Laravel Scheduler
↓
Command / Job / Closure
↓
Execute
در پروژههای حرفهای نیز بهتر است Scheduler فقط مسئول زمانبندی باشد و منطق اصلی در Command، Job و Service قرار بگیرد.
همچنین برای Taskهای حساس باید مواردی مانند withoutOverlapping، Lock، Idempotency و Transaction را متناسب با نیاز پروژه در نظر گرفت.
# سوالات متداول
Task Scheduling در Laravel چیست؟
Task Scheduling سیستم داخلی Laravel برای تعریف و مدیریت زمان اجرای وظایف مختلف مانند Command، Job و Closure است.
آیا Laravel Scheduler به Cron نیاز دارد؟
در روش معمول Production، بله. معمولاً یک Cron در سیستمعامل هر دقیقه php artisan schedule:run را اجرا میکند تا Laravel Scheduleهای موعددار را بررسی کند.
schedule:run چیست؟
این دستور Scheduleهای Laravel را بررسی میکند و Taskهایی را که زمان اجرای آنها رسیده است اجرا میکند.
php artisan schedule:run
schedule:work چیست؟
php artisan schedule:work Scheduler را بهصورت مداوم اجرا میکند و برای Development و برخی معماریهای Production کاربرد دارد.
چگونه یک Command را روزانه اجرا کنیم؟
مثلاً:
Schedule::command('report:generate')->daily();
چگونه یک Job را زمانبندی کنیم؟
مثلاً:
Schedule::job(new GenerateReport)->daily();
چگونه از اجرای همزمان یک Task جلوگیری کنیم؟
میتوان از:
->withoutOverlapping()
استفاده کرد.
چگونه Scheduleهای Laravel را ببینیم؟
با:
php artisan schedule:list
میتوانید Scheduleهای تعریفشده را بررسی کنید.
آیا Scheduler همان Queue است؟
خیر.
Scheduler مشخص میکند چه زمانی یک عملیات اجرا شود؛ Queue برای پردازش پسزمینه Jobها استفاده میشود.





