الخطوات
-
1
إنشاء أمر Artisan
أنشئ أمر Artisan جديدًا باستخدام
make:command. أعطه اسمًا وصفيًا. خاصية$signatureفي الأمر تصبح النص الذي تستخدمه لاستدعائه من المُجدوِل والطرفية.bashphp artisan make:command SendDailyReport -
2
كتابة منطق الأمر
افتح
app/Console/Commands/SendDailyReport.php. حدد$signatureو$description، ثم اكتب منطق مهمتك في دالةhandle(). أعِدCommand::SUCCESSفي النهاية حتى يعرف المُجدوِل أن الأمر اكتمل بدون أخطاء.php<?php namespace App\Console\Commands; use Illuminate\Console\Command; class SendDailyReport extends Command { protected $signature = 'report:daily'; protected $description = 'Send the daily summary report to admins'; public function handle(): int { // Your task logic here $this->info('Generating daily report...'); // e.g. Mail::to('admin@example.com')->send(new DailyReport()); $this->info('Report sent successfully.'); return Command::SUCCESS; } } -
3
تسجيل الجدول في routes/console.php (Laravel 11+)
في Laravel 11 والإصدارات الأحدث، تُعرَّف المهام المجدولة في
routes/console.phpباستخدام واجهةSchedule. هذا الملف يُحمَّل تلقائيًا — لا حاجة لتسجيل في service provider.في Laravel 10 والإصدارات الأقدم، تعرّف الجدول في دالة
schedule()فيapp/Console/Kernel.phpبدلًا من ذلك. دوال التكرار متطابقة في كلا الإصدارين.php<?php // routes/console.php (Laravel 11+) use Illuminate\Support\Facades\Schedule; Schedule::command('report:daily')->dailyAt('07:00'); // Laravel 10 — app/Console/Kernel.php // protected function schedule(Schedule $schedule): void // { // $schedule->command('report:daily')->dailyAt('07:00'); // } -
4
استخدام دالة التكرار المناسبة
يأتي Laravel مع دوال مساعدة سلسة للتكرار لكل فترة تقريبًا. بعض أكثرها استخدامًا موضح أدناه. يمكنك ربط قيود متعددة لتكوين جداول دقيقة — مثلًا
->weekdays()->hourly().phpSchedule::command('report:daily')->daily(); // midnight Schedule::command('report:daily')->dailyAt('08:00'); // 08:00 every day Schedule::command('sync:data')->everyFiveMinutes(); // every 5 min Schedule::command('sync:data')->everyFifteenMinutes(); // every 15 min Schedule::command('cleanup')->weekly()->sundays()->at('03:00'); Schedule::command('newsletter')->monthlyOn(1, '09:00'); // 1st of month Schedule::command('ping')->everyMinute(); // every minute Schedule::command('report')->weekdays()->at('09:00'); // Mon–Fri at 9am -
5
منع التشغيل المتداخل
بشكل افتراضي، إذا كان أمر مجدول لا يزال يعمل عند موعد التنفيذ التالي، يعمل كلا الـ instance في وقت واحد. أضف
->withoutOverlapping()للتأكد من أن instance واحدًا فقط يعمل في كل مرة. يستخدم Laravel قفلًا ذريًا لتطبيق هذا.phpSchedule::command('sync:orders') ->everyFiveMinutes() ->withoutOverlapping() // skip if previous run is still active ->runInBackground(); // run the command without blocking the scheduler process -
6
تسجيل مخرجات الأمر في ملف
استخدم
->appendOutputTo()لالتقاط مخرجات الأمر (كل ما يُطبع عبر$this->info()) في ملف log. هذا لا يقدّر بثمن لتشخيص فشل cron الذي يبتلعه المُجدوِل بصمت.phpSchedule::command('report:daily') ->daily() ->appendOutputTo(storage_path('logs/daily-report.log')); -
7
إضافة إدخال cron واحد على الخادم
على خادم الإنتاج، أضف إدخالًا واحدًا فقط في cron — يُشغّل
schedule:runكل دقيقة. يقرأ Laravel جميع مهامك المجدولة من هذا الأمر الواحد ويقرر أيها تُشغَّل بناءً على الوقت الحالي.افتح crontab بالأمر
crontab -eوأضف السطر أدناه. استبدل المسار بمسار مشروعك الفعلي ومسار PHP (اعثر عليه بـwhich php).bash* * * * * cd /var/www/myapp.com && php artisan schedule:run >> /dev/null 2>&1 -
8
اختبار الجدول محليًا
لا تحتاج إلى انتظار cron لاختبار مهامك. استخدم
schedule:runيدويًا لتشغيل جميع المهام المستحقة الآن، أوschedule:workلتشغيل المُجدوِل في المقدمة كل دقيقة (مفيد أثناء التطوير).bash# Trigger all due tasks once (same as what cron does) php artisan schedule:run # Run scheduler in foreground, polling every minute php artisan schedule:work # List all registered tasks and their next run time php artisan schedule:list
نصائح ومحاذير
- استخدم دائمًا <code>->withoutOverlapping()</code> على أي مهمة تتعامل مع APIs خارجية أو عمليات قاعدة بيانات ثقيلة — التشغيلات المكررة تسبب فسادًا خفيًا في البيانات يصعب تشخيصه.
- شغّل <code>php artisan schedule:list</code> للتحقق من وقت التشغيل المتوقع التالي لكل مهمة قبل النشر في الإنتاج.
- اضبط إدخال cron ليعمل بمستخدم خادم الويب (مثلًا <code>www-data</code>) لا root، حتى تتطابق صلاحيات الملفات التي تُنشأ أثناء المهمة مع ما يتوقعه التطبيق.
- استخدم دوال الرد <code>->onSuccess()</code> و<code>->onFailure()</code> لإرسال إشعار أو كتابة log عند اكتمال مهمة مجدولة أو فشلها.
خاتمة
أصبح لديك الآن مُجدوِل مهام يعمل بشكل كامل — إدخال cron واحد يُشغّل جميع أوامرك المجدولة مع حماية من التداخل وتسجيل المخرجات. من هنا، استكشف ->sendOutputTo() مع إشعار Slack أو بريد إلكتروني عند الفشل، أو انظر في تشغيل closures ومهام مجهولة مباشرةً في المُجدوِل للمهام الخفيفة.