البرمجة مبتدئ 8 دقيقة

كيفية جدولة المهام الدورية في Laravel

مُجدوِل المهام في Laravel يتيح لك تعريف جميع مهام cron بلغة PHP — لا حاجة لتعديل crontab الخادم عند كل مهمة جديدة. تسجّل إدخالًا واحدًا في cron يستدعي php artisan schedule:run كل دقيقة، ويتولى Laravel الباقي.

يغطي هذا الدليل إنشاء أمر Artisan مخصص، تسجيله في المُجدوِل، ضبط التكرار، منع التشغيل المتداخل، وتسجيل المخرجات — كل ذلك باستخدام أسلوب Laravel 11 الحديث (مع ملاحظة حول الطريقة القديمة المعتمدة على Kernel).

الخطوات

  1. 1

    إنشاء أمر Artisan

    أنشئ أمر Artisan جديدًا باستخدام make:command. أعطه اسمًا وصفيًا. خاصية $signature في الأمر تصبح النص الذي تستخدمه لاستدعائه من المُجدوِل والطرفية.

    bash
    php artisan make:command SendDailyReport
  2. 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. 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. 4

    استخدام دالة التكرار المناسبة

    يأتي Laravel مع دوال مساعدة سلسة للتكرار لكل فترة تقريبًا. بعض أكثرها استخدامًا موضح أدناه. يمكنك ربط قيود متعددة لتكوين جداول دقيقة — مثلًا ->weekdays()->hourly().

    php
    Schedule::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. 5

    منع التشغيل المتداخل

    بشكل افتراضي، إذا كان أمر مجدول لا يزال يعمل عند موعد التنفيذ التالي، يعمل كلا الـ instance في وقت واحد. أضف ->withoutOverlapping() للتأكد من أن instance واحدًا فقط يعمل في كل مرة. يستخدم Laravel قفلًا ذريًا لتطبيق هذا.

    php
    Schedule::command('sync:orders')
        ->everyFiveMinutes()
        ->withoutOverlapping()  // skip if previous run is still active
        ->runInBackground();    // run the command without blocking the scheduler process
  6. 6

    تسجيل مخرجات الأمر في ملف

    استخدم ->appendOutputTo() لالتقاط مخرجات الأمر (كل ما يُطبع عبر $this->info()) في ملف log. هذا لا يقدّر بثمن لتشخيص فشل cron الذي يبتلعه المُجدوِل بصمت.

    php
    Schedule::command('report:daily')
        ->daily()
        ->appendOutputTo(storage_path('logs/daily-report.log'));
  7. 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. 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 ومهام مجهولة مباشرةً في المُجدوِل للمهام الخفيفة.

#Laravel #Cron #Scheduler
العودة إلى جميع الأدلة

هل تحتاج مساعدة في مشروعك؟

احجز استشارة مجانية لمدة 30 دقيقة لمناقشة تحدياتك التقنية واستكشاف الحلول معًا.