إطار Laravel

أوامر Artisan Console

15 دقيقة الدرس 25 من 45

أوامر Artisan Console

Artisan هي واجهة سطر الأوامر في Laravel، توفر العشرات من الأوامر المفيدة لبناء تطبيقك. بالإضافة إلى استخدام الأوامر المدمجة، يمكنك إنشاء أوامر مخصصة لأتمتة المهام، وتشغيل المهام المجدولة، ومعالجة البيانات، والمزيد. يغطي هذا الدرس إنشاء والعمل مع أوامر Artisan المخصصة.

فهم أوامر Artisan

أوامر Artisan هي فئات PHP يمكن تنفيذها من سطر الأوامر. إنها مثالية لـ:

  • المهام الآلية ومهام cron
  • معالجة البيانات والاستيراد
  • صيانة وتنظيف قاعدة البيانات
  • إنشاء التقارير
  • إرسال الإشعارات أو البريد الإلكتروني بكميات كبيرة
  • تشغيل الاختبارات أو فحوصات الصحة
إنشاء أمر:
// إنشاء أمر جديد
php artisan make:command SendNewsletterCommand

// app/Console/Commands/SendNewsletterCommand.php
namespace App\Console\Commands;

use Illuminate\Console\Command;

class SendNewsletterCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'newsletter:send';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Send newsletter to all subscribers';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $this->info('Sending newsletter...');

        // منطق الأمر هنا

        $this->info('Newsletter sent successfully!');

        return Command::SUCCESS;
    }
}
تسجيل الأمر: يكتشف Laravel تلقائياً ويسجل جميع الأوامر في دليل app/Console/Commands. يمكنك تشغيل أمرك باستخدام php artisan newsletter:send.

توقيع الأمر والوسائط

توقيع الأمر يحدد كيفية استدعاء الأمر، بما في ذلك الوسائط والخيارات:

توقيعات الأوامر:
namespace App\Console\Commands;

use Illuminate\Console\Command;

class UserManagementCommand extends Command
{
    // أمر بسيط
    protected $signature = 'user:create';

    // مع وسيط مطلوب
    protected $signature = 'user:create {name}';

    // مع وسيط اختياري
    protected $signature = 'user:create {name?}';

    // مع قيمة افتراضية
    protected $signature = 'user:create {name=John}';

    // مع وصف للوسيط
    protected $signature = 'user:create {name : The name of the user}';

    // وسائط متعددة
    protected $signature = 'user:create {name} {email}';

    // مع خيار (علم)
    protected $signature = 'user:create {name} {--admin}';

    // خيار مع قيمة
    protected $signature = 'user:create {name} {--role=}';

    // خيار مع قيمة افتراضية
    protected $signature = 'user:create {name} {--role=user}';

    // اختصار الخيار
    protected $signature = 'user:create {name} {--R|role=}';

    // مصفوفة خيارات
    protected $signature = 'user:create {name} {--role=*}';

    // مثال كامل
    protected $signature = 'user:create
                            {name : The user name}
                            {email : The user email}
                            {--admin : Make user an administrator}
                            {--role=* : Assign roles to user}
                            {--force : Force creation without confirmation}';

    protected $description = 'Create a new user account';

    public function handle()
    {
        // الوصول إلى الوسائط
        $name = $this->argument('name');
        $email = $this->argument('email');

        // الوصول إلى الخيارات
        $isAdmin = $this->option('admin');
        $roles = $this->option('role');
        $force = $this->option('force');

        // الحصول على جميع الوسائط/الخيارات
        $allArguments = $this->arguments();
        $allOptions = $this->options();

        return Command::SUCCESS;
    }
}

// أمثلة الاستخدام:
// php artisan user:create "John Doe" john@example.com
// php artisan user:create "Jane" jane@example.com --admin
// php artisan user:create "Bob" bob@example.com --role=editor --role=author
// php artisan user:create "Alice" alice@example.com --force -R admin

الإدخال والإخراج التفاعلي

يمكن للأوامر التفاعل مع المستخدمين من خلال طرق الإدخال والإخراج المختلفة:

طرق الإدخال والإخراج:
namespace App\Console\Commands;

use Illuminate\Console\Command;

class InteractiveCommand extends Command
{
    protected $signature = 'app:interactive';
    protected $description = 'Demonstrate interactive input/output';

    public function handle()
    {
        // طرق الإخراج
        $this->info('This is informational text');
        $this->comment('This is a comment');
        $this->question('This is a question');
        $this->error('This is an error message');
        $this->warn('This is a warning');
        $this->line('This is plain text');

        // سطر جديد
        $this->newLine();
        $this->newLine(3); // ثلاثة أسطر فارغة

        // اسأل عن الإدخال
        $name = $this->ask('What is your name?');
        $email = $this->ask('What is your email?', 'default@example.com');

        // إدخال سري (كلمة المرور)
        $password = $this->secret('What is the password?');

        // تأكيد
        if ($this->confirm('Do you want to continue?')) {
            $this->info('Continuing...');
        }

        // تأكيد مع افتراضي
        if ($this->confirm('Delete all records?', false)) {
            // يعمل فقط إذا أكد المستخدم صراحة
        }

        // اختيار الخيار
        $role = $this->choice(
            'What role should the user have?',
            ['admin', 'editor', 'viewer'],
            0  // الفهرس الافتراضي
        );

        // اختيار متعدد
        $roles = $this->choice(
            'Select roles (separate multiple with comma)',
            ['admin', 'editor', 'viewer'],
            0,
            $maxAttempts = null,
            $allowMultipleSelections = true
        );

        // توقع - إكمال تلقائي
        $country = $this->anticipate('Select country', ['USA', 'UK', 'Canada']);

        // إخراج الجدول
        $this->table(
            ['Name', 'Email', 'Role'],
            [
                ['John Doe', 'john@example.com', 'Admin'],
                ['Jane Smith', 'jane@example.com', 'Editor'],
            ]
        );

        return Command::SUCCESS;
    }
}
تجربة المستخدم: استخدم الألوان والتنسيق لجعل إخراج الأمر واضحاً وسهل القراءة. استخدم confirm() للعمليات المدمرة لمنع الحوادث.

أشرطة التقدم وتتبع المهام

للعمليات طويلة المدى، توفر أشرطة التقدم ملاحظات بصرية:

مؤشرات التقدم:
namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\User;

class ProcessUsersCommand extends Command
{
    protected $signature = 'users:process';
    protected $description = 'Process all users';

    public function handle()
    {
        $users = User::all();

        // شريط تقدم بسيط
        $bar = $this->output->createProgressBar($users->count());
        $bar->start();

        foreach ($users as $user) {
            // معالجة المستخدم
            $this->processUser($user);

            $bar->advance();
        }

        $bar->finish();
        $this->newLine();

        // مساعد withProgressBar
        $this->withProgressBar($users, function ($user) {
            $this->processUser($user);
        });

        $this->newLine();

        return Command::SUCCESS;
    }

    protected function processUser($user)
    {
        // محاكاة المعالجة
        sleep(0.1);
    }
}

استدعاء أوامر أخرى

يمكن للأوامر استدعاء أوامر Artisan أخرى برمجياً:

استدعاء الأوامر:
namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;

class DeployCommand extends Command
{
    protected $signature = 'app:deploy';
    protected $description = 'Deploy the application';

    public function handle()
    {
        $this->info('Starting deployment...');

        // استدعاء أمر آخر
        $this->call('down');

        // استدعاء مع وسائط وخيارات
        $this->call('migrate', [
            '--force' => true,
        ]);

        // استدعاء بصمت (بدون إخراج)
        $this->callSilently('db:seed');

        // استدعاء والتقاط الإخراج
        $exitCode = $this->call('config:cache');

        if ($exitCode === 0) {
            $this->info('Config cached successfully');
        }

        // استخدام Artisan facade
        Artisan::call('optimize');

        // الحصول على الإخراج من Artisan facade
        Artisan::call('inspire');
        $output = Artisan::output();
        $this->line($output);

        $this->call('up');
        $this->info('Deployment complete!');

        return Command::SUCCESS;
    }
}

حقن التبعيات في الأوامر

تدعم الأوامر حقن التبعيات في طريقة handle:

حقن التبعيات:
namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Services\ReportGenerator;
use App\Services\EmailService;
use Illuminate\Support\Facades\Storage;

class GenerateReportCommand extends Command
{
    protected $signature = 'report:generate {type}';
    protected $description = 'Generate and email reports';

    /**
     * التبعيات محقونة في طريقة handle
     */
    public function handle(
        ReportGenerator $generator,
        EmailService $emailService
    ) {
        $type = $this->argument('type');

        $this->info("Generating {$type} report...");

        // استخدام الخدمات المحقونة
        $report = $generator->generate($type);

        $filename = "report-{$type}-" . now()->format('Y-m-d') . '.pdf';
        Storage::put("reports/{$filename}", $report);

        $this->info('Report generated: ' . $filename);

        if ($this->confirm('Email the report?')) {
            $email = $this->ask('Email address?');
            $emailService->sendReport($email, $report);
            $this->info('Report emailed to ' . $email);
        }

        return Command::SUCCESS;
    }
}

جدولة الأوامر

يمكن جدولة الأوامر للتشغيل تلقائياً باستخدام جدولة المهام في Laravel:

جدولة الأوامر:
// app/Console/Kernel.php
namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    protected function schedule(Schedule $schedule): void
    {
        // تشغيل الأمر كل يوم في منتصف الليل
        $schedule->command('newsletter:send')
                 ->daily();

        // تشغيل الأمر كل ساعة
        $schedule->command('backup:database')
                 ->hourly();

        // تشغيل الأمر مع وسائط وخيارات
        $schedule->command('report:generate monthly --email')
                 ->monthlyOn(1, '09:00');

        // استخدام طريقة call
        $schedule->call(function () {
            // منطق closure
        })->everyFifteenMinutes();

        // خيارات التردد
        $schedule->command('emails:send')->everyMinute();
        $schedule->command('backup:run')->everyFiveMinutes();
        $schedule->command('report:weekly')->weekly();
        $schedule->command('cleanup')->dailyAt('13:00');
        $schedule->command('invoice:generate')->monthlyOn(15, '08:00');

        // الجدولة الشرطية
        $schedule->command('emails:send')
                 ->daily()
                 ->when(function () {
                     return date('w') !== 0; // لا تعمل يوم الأحد
                 });

        // منع التداخلات
        $schedule->command('process:large-dataset')
                 ->hourly()
                 ->withoutOverlapping();

        // التشغيل في الخلفية
        $schedule->command('backup:run')
                 ->daily()
                 ->runInBackground();

        // إرسال الإخراج إلى ملف
        $schedule->command('report:generate')
                 ->daily()
                 ->sendOutputTo(storage_path('logs/report.log'));
    }
}

// إعداد مهمة cron لتشغيل الجدولة (مرة واحدة فقط):
// * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
تمرين عملي 1: أنشئ أمراً باسم users:cleanup يحذف المستخدمين الذين لم يسجلوا الدخول لأكثر من 180 يوماً. أضف خيار --dry-run لمعاينة ما سيتم حذفه دون الحذف فعلياً. أظهر مطالبة تأكيد قبل الحذف (ما لم يتم استخدام --force). اعرض جدولاً للمستخدمين المراد حذفهم واستخدم شريط تقدم أثناء الحذف.
تمرين عملي 2: ابنِ أمر report:sales يقبل وسيط {period} (daily/weekly/monthly) وينشئ تقرير مبيعات. اسأل عن مستلمي البريد الإلكتروني بشكل تفاعلي إذا كان خيار --email موجوداً. احقن تبعيات ReportGenerator و EmailService. اعرض ملخص التقرير في جدول منسق واحفظ التقرير في التخزين.
تمرين عملي 3: أنشئ أمر db:backup-and-optimize يستدعي أوامر متعددة بالتسلسل: يقوم بعمل نسخة احتياطية من قاعدة البيانات، ويشغل الهجرات، ويحسن الجداول، وينظف السجلات القديمة. أضف معالجة أخطاء مناسبة والتراجع إذا فشلت أي خطوة. جدوله للتشغيل يومياً في الساعة 3 صباحاً في Kernel.

الخلاصة

أوامر Artisan هي أدوات قوية لأتمتة تطبيقات Laravel:

  • توقيع الأمر: تعريف الوسائط والخيارات بمرونة
  • الإدخال/الإخراج التفاعلي: طرح الأسئلة، إظهار التقدم، تنسيق الإخراج
  • استدعاء الأوامر: تنفيذ أوامر أخرى برمجياً
  • حقن التبعيات: حقن الخدمات في طريقة handle
  • الجدولة: أتمتة تنفيذ الأوامر مع cron
  • أكواد الإرجاع: استخدام Command::SUCCESS و Command::FAILURE

مع استعلامات Eloquent المتقدمة، وموارد API، وحاوية الخدمات، وموفري الخدمات، وأوامر Artisan، لديك الآن فهم شامل للبنية الأساسية لـ Laravel ويمكنك بناء تطبيقات متطورة بكفاءة.