أصبح الذكاء الاصطناعي جزءًا أساسيًا من سير العمل اليومي لمطوري الويب، لكن المشكلة التي واجهت مطوري Laravel طويلًا هي أن أدوات الذكاء الاصطناعي لا تعرف شيئًا عن مشروعك تحديدًا: لا تعرف إصدار الإطار الذي تستخدمه، ولا أسماء أعمدة قاعدة بياناتك، ولا الأعراف التي اتفق عليها فريقك. النتيجة كود يبدو صحيحًا ولا يعمل.

هنا يأتي دور Laravel Boost، الحزمة الرسمية من فريق Laravel التي تسدّ هذه الفجوة عبر أربع آليات مختلفة، وليس عبر «سحر» واحد كما يُشاع.

ما هي Laravel Boost؟

Laravel Boost حزمة تطوير رسمية مفتوحة المصدر (رخصة MIT) تشغّل خادم MCP محليًا داخل مشروعك، وتولّد ملفات توجيهات ومهارات مخصّصة للحزم المثبتة لديك. الهدف ليس أن يكتب الذكاء الاصطناعي بدلًا عنك، بل أن يكتب كودًا يتوافق مع مشروعك أنت: إصدارك، مخطط قاعدة بياناتك، وأعراف فريقك.

توضيح مهم: Boost لا يقرأ ملفات مشروعك ولا «يحللها» تلقائيًا. قراءة الملفات وظيفة المحرر أو الوكيل البرمجي نفسه (Cursor، Claude Code، Copilot…). ما يفعله Boost هو تزويد ذلك الوكيل بأدوات يستدعيها عند الحاجة، وبمعرفة جاهزة عن الإطار والحزم.

المشكلة التي تحلها Boost

  • اقتراحات لا تناسب إصدارك: نماذج الذكاء الاصطناعي مدرّبة على كود قديم، فتقترح صياغات لم تعد مدعومة في الإصدار الحديث.
  • جهل ببنية البيانات: لا يعرف الوكيل أن العمود اسمه total_amount لا total، ولا أن العلاقة اسمها categories لا category.
  • تجاهل أعراف الفريق: قد يكتب حلًا صحيحًا تقنيًا لكنه يخالف القرارات المتفق عليها في مشروعك.
  • ضياع الوقت في التصحيح: بدل توفير الوقت، تقضيه في مراجعة كود مقترح وإصلاحه.

كيف تعمل Laravel Boost فعليًا؟

تعتمد Boost على أربع آليات منفصلة، وفهم الفرق بينها هو ما يفرّق بين استخدام سطحي واستخدام فعّال.

1. خادم MCP والأدوات

بروتوكول MCP (Model Context Protocol) معيار مفتوح يسمح للوكيل باستدعاء أدوات محددة بطريقة منظمة. Boost يشغّل خادمًا محليًا عبر الأمر php artisan boost:mcp ويعرض الأدوات التالية:

أدوات MCP المتاحة في Laravel Boost
الأداةما تقدمه
Application Infoإصدارا PHP و Laravel، محرك قاعدة البيانات، الحزم المثبتة بإصداراتها، وقائمة نماذج Eloquent
Database Schemaقراءة مخطط قاعدة البيانات: الجداول والأعمدة وأنواعها
Database Queryتنفيذ استعلام فعلي على قاعدة البيانات
Database Connectionsالاتصالات المتاحة والاتصال الافتراضي
Search Docsالبحث في توثيق منظومة Laravel حسب الحزم المثبتة لديك
Last Error و Read Log Entriesقراءة آخر خطأ أو آخر عدد من مدخلات السجل
Browser Logsقراءة سجلات وأخطاء المتصفح
Get Absolute URLتحويل المسارات النسبية إلى روابط مطلقة صحيحة
Record Ruleتسجيل قاعدة دائمة في .ai/rules ليرثها كل وكيل لاحق

أداة Search Docs هي الأهم وغالبًا الأقل شهرة: تستعلم من واجهة توثيق تستضيفها Laravel تضم أكثر من 17,000 مقطع معرفي خاص بالإطار ومنظومته، مع بحث دلالي قائم على embeddings. بدل أن يعتمد الوكيل على ذاكرته المدرَّبة قبل سنة، يقرأ التوثيق المطابق لإصدارك الآن.

2. التوجيهات (AI Guidelines)

ملفات نصية تُولَّد داخل مشروعك (CLAUDE.md، AGENTS.md، وغيرها حسب الوكيل) وتُحمَّل مقدمًا مع بداية كل جلسة. تحتوي على أعراف Laravel وأفضل الممارسات الخاصة بالحزم المثبتة لديك وبإصداراتها تحديدًا: الإطار، Livewire، Inertia، Pest، Tailwind، Filament وغيرها.

3. المهارات (Agent Skills)

وحدات معرفة مركّزة تُفعَّل عند الحاجة فقط. الفرق عن التوجيهات جوهري: التوجيهات دائمة الحضور في السياق فتبقى مختصرة، بينما المهارة تُحمَّل فقط حين يعمل الوكيل في مجالها، فتحتمل تفاصيل أعمق دون تضخيم السياق. تُثبَّت تلقائيًا حسب محتوى composer.json؛ فإن كان مشروعك يستخدم Livewire ستُثبَّت مهارة livewire-development.

4. قواعد المشروع (Project Rules)

التوجيهات والمهارات تعلّم الوكيل كيف يكتب Laravel. أما قواعد المشروع فتعلّمه كيف يكتب تطبيقك أنت: القرارات التي اتخذها فريقك، والتفضيلات التي يصعب على الوكيل التزامها، والمصائد التي لا يمكن استنتاجها من الكود المحيط. سنفرد لها قسمًا كاملًا بعد قليل لأنها المفتاح الحقيقي للأمثلة التي ستراها.

المتطلبات

  • PHP 8.2 فأعلى.
  • Laravel 11 أو 12 أو 13 — هذا هو الحد الأدنى لإصدار Boost 2.x الحالي.
  • مشاريع Laravel 10 تحتاج البقاء على فرع Boost 1.x، فقد رُفع الحد الأدنى في الإصدار الثاني.
  • محرر أو وكيل برمجي يدعم MCP.

التثبيت والإعداد

ثبّت الحزمة كاعتمادية تطوير فقط:

composer require laravel/boost --dev

ثم شغّل أمر التثبيت:

php artisan boost:install

الأمر تفاعلي: سيسألك عن المحرر أو الوكيل الذي تستخدمه، وعن المزايا التي تريد تفعيلها، ثم يولّد ملفات التوجيهات والمهارات المناسبة لمشروعك. في معظم المحررات يُفعَّل خادم MCP تلقائيًا؛ وإن لم يحدث ذلك تحتاج خطوة تفعيل يدوية واحدة (تفعيل laravel-boost من إعدادات MCP، أو أمر واحد مثل claude mcp add -s local -t stdio laravel-boost php artisan boost:mcp).

ماذا ترفع إلى Git وماذا تتجاهل؟

هذه نقطة يخطئ فيها كثيرون:

  • أضف إلى .gitignore: ملف .mcp.json، وملفات التوجيهات المولَّدة (CLAUDE.md، AGENTS.md، junie/…)، وملف boost.json — لأنها تُولَّد تلقائيًا مع كل تشغيل للأوامر.
  • ارفع إلى المستودع: مجلد .ai/rules، لأن قواعد المشروع مِلك للفريق لا للمطور الواحد.

الحفاظ على تحديث الموارد

عند ترقية حزمة، تصبح التوجيهات المولَّدة قديمة. حدّثها بـ:

php artisan boost:update

وإن أردت أن يفحص المشروع بحثًا عن حزم جديدة مثبتة ويعرض عليك نشر توجيهاتها:

php artisan boost:update --discover

ويمكنك أتمتة ذلك بربطه بسكربتات Composer:

{
    "scripts": {
        "post-update-cmd": [
            "@php artisan boost:update --ansi"
        ]
    }
}

تعليم Boost أعراف مشروعك

هنا يكمن الفرق بين مطور يستخدم Boost كأداة بحث في التوثيق، ومطور يجعله يكتب بأسلوب فريقه.

تسجيل القواعد

القواعد ملفات Markdown داخل .ai/rules، ولتسجيل واحدة يكفي أن تطلب من الوكيل تذكّرها بلغة طبيعية:

Remember that all money values are stored as integer cents, never as floats.

عندها يستدعي الوكيل أداة record-rule فيسجّل القاعدة تحت المجال المناسب ويحدّث ملف الفهرس .ai/rules/index.md، وهو ملف يربط أنماط المسارات بملفات القواعد. الوكلاء مُوجَّهون لمراجعة هذا الفهرس قبل التخطيط أو تعديل أي ملف، فلا تُحمَّل القاعدة إلا حين تكون ذات صلة فعلًا.

مثال على ملف قاعدة:

---
paths:
  - app/Http/Controllers/**
---

# Http Controllers

## Extend BaseController for tenant scoping

All controllers must extend `App\Http\Controllers\BaseController`, which applies
the current tenant's query scope. Extending Laravel's base controller directly
will leak data across tenants.

تحذير عملي: لا تنشئ ملفات القواعد يدويًا. Boost يعيد توليد ملف الفهرس عند التسجيل عبر الأداة، والقاعدة المضافة يدويًا لن يكتشفها أي وكيل حتى يُعاد توليد الفهرس.

استخراج الأعراف من مشروع قائم

تسجيل القواعد واحدة تلو الأخرى ممتاز للمستقبل، لكن مشروعك القائم يحتوي أصلًا على سنوات من الأعراف. لهذا توجد مهارة infer-conventions. اطلب من وكيلك:

Use the infer-conventions skill

ستمسح المهارة تطبيقك عبر قائمة من أبعاد أعراف Laravel — التحقق، المتحكمات، الصلاحيات، النماذج، البنية المعمارية، الاختبارات، الواجهة، قاعدة البيانات، وأوامر الطرفية — ثم تمرّ مرورًا مفتوحًا على أنماط مثل الأصناف الأساسية والسمات المشتركة.

والأهم في تصميمها: توثّق ما يفعله كودك فعلًا لا ما يُفترض أن يفعله، وتتجاهل الإعدادات الافتراضية للإطار وكل ما يفرضه Pint أو Rector أصلًا، وتُبلغك عن الأنماط المتضاربة بدل تسجيلها كقاعدة. وقبل كتابة أي شيء تعرض عليك كل عرف اكتشفته مع الأدلة الداعمة لموافقتك.

ولتعطيل قواعد المشروع كليًا (فتُزال أداة record-rule ويتوقف Boost عن إدارة المجلد):

BOOST_RULES_ENABLED=false

أمثلة عملية

في كل مثال، انتبه إلى أي آلية قدّمت أي معلومة. هذا ما يجعل النتيجة قابلة للتكرار عندك بدل أن تبدو صدفة.

مثال 1: متحكم يعرف علاقاتك الحقيقية

الطلب: «اكتب متحكمًا لعرض المنتجات مع الفئات».

بدون سياق، ستحصل غالبًا على:

public function index()
{
    $products = Product::with('category')->get();

    return view('products.index', compact('products'));
}

المشكلة أن العلاقة في مشروعك اسمها categories لا category، وأن get() على جدول منتجات حقيقي كارثة أداء.

مع Boost:

public function index(): View
{
    $products = Product::query()
        ->with('categories')
        ->active()
        ->latest('published_at')
        ->paginate(15);

    return view('products.index', compact('products'));
}

مصدر كل معلومة:

  • categories و published_at: من أداة Application Info التي تعرض نماذج Eloquent، ومن قراءة الوكيل لملف النموذج.
  • active(): نطاق (scope) معرّف في نموذجك، يكتشفه الوكيل من الملف نفسه.
  • تفضيل paginate على get: من التوجيهات العامة لـ Laravel.

مثال 2: ترحيل يتبع أعراف قاعدة بياناتك

الطلب: «أضف جدول orders مرتبطًا بـ users».

بدون سياق:

Schema::create('orders', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained();
    $table->decimal('total', 8, 2);
    $table->timestamps();
});

مع Boost وقواعد مشروع مسجَّلة:

use App\Enums\OrderStatus;

Schema::create('orders', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->string('order_number')->unique();
    $table->decimal('total_amount', 10, 2);
    $table->string('status')->default(OrderStatus::Pending->value);
    $table->timestamp('ordered_at');
    $table->timestamps();
    $table->softDeletes();
});

مع التحويل المناسب في النموذج:

protected function casts(): array
{
    return [
        'status' => OrderStatus::class,
        'ordered_at' => 'datetime',
        'total_amount' => 'decimal:2',
    ];
}

مصدر كل معلومة:

  • نمط تسمية total_amount ودقة 10,2: من أداة Database Schema التي ترى الأعمدة الموجودة فعلًا.
  • استخدام softDeletes و order_number الفريد: من قواعد المشروع، أو من مهارة infer-conventions بعد مسح الجداول القائمة.
  • استخدام cascadeOnDelete() بدل onDelete('cascade')، وعمود string مع Backed Enum بدل نوع enum في قاعدة البيانات: من التوجيهات. النوع enum يجعل إضافة حالة جديدة لاحقًا تعديلًا مؤلمًا على الجدول، بينما تحويل PHP يمنحك نفس الأمان دون هذا القيد.

مثال 3: استعلام معقّد بلا أخطاء صامتة

الطلب: «اعرض المستخدمين الذين لديهم طلبات في الشهر الأخير، مرتّبين حسب عدد الطلبات».

بدون سياق:

$users = User::whereHas('orders', function ($query) {
    $query->where('created_at', '>=', now()->subMonth());
})->get();

الخطأ هنا مزدوج: الحقل الصحيح هو ordered_at لا created_at، والاستعلام لا يرتّب أصلًا.

مع Boost:

$range = [now()->subMonth()->startOfDay(), now()->endOfDay()];

$recent = fn ($query) => $query->whereBetween('ordered_at', $range);

$users = User::query()
    ->with(['orders' => fn ($query) => $recent($query)
        ->select('id', 'user_id', 'order_number', 'total_amount', 'status')])
    ->whereHas('orders', $recent)
    ->withCount(['orders as recent_orders_count' => $recent])
    ->orderByDesc('recent_orders_count')
    ->get();

ثلاث نقاط تستحق الانتباه:

  • الاسم المستعار في withCount ضروري. لو كتبت withCount('orders') فقط لعدّ كل طلبات المستخدم منذ بداية التاريخ، فيصبح الترتيب مناقضًا لهدف الاستعلام. هذا خطأ منطقي صامت: الكود يعمل ولا يرمي أي استثناء، لكن النتيجة خاطئة.
  • تضمين user_id في select إلزامي. بدونه ينكسر التحميل المسبق (eager loading) لأن Laravel لن يجد المفتاح الأجنبي الذي يربط الطلبات بأصحابها.
  • استخراج الشرط في متغير واحد يمنع التكرار الثلاثي ويضمن أن أي تعديل على المدى الزمني يسري على المواضع الثلاثة معًا.

مثال 4: قواعد تحقق مبنية على المخطط الفعلي

الطلب: «اكتب تحققًا لتحديث بيانات المنتج».

بدون سياق:

public function rules()
{
    return [
        'name' => 'required|string|max:255',
        'price' => 'required|numeric',
        'description' => 'nullable|string',
    ];
}

مع Boost:

use Illuminate\Validation\Rule;

public function rules(): array
{
    return [
        'name_ar' => ['required', 'string', 'max:255'],
        'name_en' => ['required', 'string', 'max:255'],
        'description_ar' => ['nullable', 'string', 'max:1000'],
        'description_en' => ['nullable', 'string', 'max:1000'],
        'price' => ['required', 'numeric', 'min:0.01', 'max:999999.99'],
        'discount_price' => ['nullable', 'numeric', 'min:0', 'lt:price'],
        'category_id' => ['required', 'integer', Rule::exists('categories', 'id')],
        'sku' => [
            'required',
            'string',
            'max:50',
            Rule::unique('products', 'sku')->ignore($this->route('product')),
        ],
        'stock_quantity' => ['required', 'integer', 'min:0'],
        'is_active' => ['sometimes', 'boolean'],
        'images' => ['nullable', 'array', 'max:5'],
        'images.*' => ['image', 'mimes:jpeg,png,webp', 'max:2048'],
    ];
}

مصدر كل معلومة:

  • وجود عمودَي name_ar و name_en، وحدود الأطوال 255 و 1000، ووجود category_id: من أداة Database Schema مباشرة.
  • استخدام صيغة المصفوفة بدل السلسلة النصية، وتمرير $this->route('product') إلى ignore() عند التحديث: من التوجيهات.
  • min:0.01 على السعر: قاعدة مشروع تمنع سعرًا صفريًا، وهي أيضًا ما يحمي حساب نسبة الخصم في المثال التالي من القسمة على صفر.

انتبه: القاعدة lt:price تعمل فقط إذا كان الحقل price مُرسَلًا في الطلب نفسه. في نموذج تحديث جزئي ستحتاج قاعدة مخصّصة تقارن بالقيمة المخزّنة.

مثال 5: مورد API متّسق مع بقية المشروع

الطلب: «اكتب مورد API للمنتج».

بدون سياق:

public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'price' => $this->price,
        'created_at' => $this->created_at,
    ];
}

مع Boost:

use Illuminate\Http\Request;
use Illuminate\Support\Number;

public function toArray(Request $request): array
{
    $locale = in_array(app()->getLocale(), ['ar', 'en'], true)
        ? app()->getLocale()
        : 'en';

    return [
        'id' => $this->id,
        'name' => $this->{"name_{$locale}"},
        'description' => $this->{"description_{$locale}"},
        'sku' => $this->sku,
        'price' => [
            'amount' => (float) $this->price,
            'formatted' => Number::currency((float) $this->price, config('app.currency')),
            'discount' => $this->discount_price === null ? null : [
                'amount' => (float) $this->discount_price,
                'formatted' => Number::currency((float) $this->discount_price, config('app.currency')),
                'percentage' => (int) round(
                    (($this->price - $this->discount_price) / $this->price) * 100
                ),
            ],
        ],
        'stock' => [
            'quantity' => $this->stock_quantity,
            'available' => $this->stock_quantity > 0,
            'status' => $this->getStockStatus(),
        ],
        'categories' => CategoryResource::collection($this->whenLoaded('categories')),
        'images' => ImageResource::collection($this->whenLoaded('images')),
        'is_active' => (bool) $this->is_active,
        'created_at' => $this->created_at?->toIso8601String(),
        'updated_at' => $this->updated_at?->toIso8601String(),
    ];
}

مصدر كل معلومة:

  • أسلوب التعدد اللغوي عبر أعمدة منفصلة (لا حقل JSON مترجم): من المخطط، ويجب أن يكون متّسقًا مع مثال التحقق أعلاه — الخلط بين الأسلوبين في مشروع واحد خطأ شائع.
  • CategoryResource::collection لا new CategoryResource: لأن العلاقة جمع، وتمرير مجموعة إلى مورد مفرد يعطي مخرجات مشوّهة.
  • Number::currency() بدل number_format مع لصق رمز العملة يدويًا: من التوجيهات، ويمنحك تنسيقًا واعيًا باللغة.
  • توقيع toArray(Request $request): array: التوقيع الصحيح في الإصدارات الحديثة.

ملاحظة معمارية: تخزين المبالغ كـ decimal ثم تحويلها إلى float مقبول في متجر بسيط، لكنه مصدر أخطاء تقريب في الأنظمة المالية. القاعدة الأكثر أمانًا هي تخزين المبالغ كأعداد صحيحة بوحدة القرش، وهي بالضبط نوع القرار الذي يستحق أن يُسجَّل كقاعدة مشروع ليلتزم به كل وكيل لاحقًا.

المحررات والوكلاء المدعومون

Boost يعمل مع أي أداة تدعم MCP، ويوفّر إعدادًا جاهزًا للأشهر منها:

  • Cursor — محرر مبني على VS Code بقدرات وكيل متقدمة.
  • Claude Code — وكيل برمجي من Anthropic يعمل في الطرفية وداخل المحررات.
  • GitHub Copilot (VS Code) — يدعم اليوم نماذج من مزوّدين متعددين لا مزوّدًا واحدًا.
  • PhpStorm و Junie — من JetBrains.
  • Codex CLI و Gemini CLI.

وإن لم تكن أداتك مدعومة، يمكنك إضافتها بنفسك عبر صنف يرث Laravel\Boost\Install\Agents\Agent وينفّذ العقود المناسبة (SupportsGuidelines، SupportsMcp، SupportsSkills)، ثم تسجّله في AppServiceProvider.

الفوائد العملية

توثيق مطابق لإصدارك
بدل اقتراحات مبنية على ذاكرة النموذج القديمة، يستعلم الوكيل من توثيق حيّ مربوط بالحزم المثبتة عندك وإصداراتها.
أسماء وأنواع حقيقية
أداة المخطط تنهي فئة كاملة من الأخطاء: أعمدة غير موجودة، أنواع خاطئة، علاقات مُخترعة.
أعراف قابلة للمشاركة
قواعد المشروع تُرفع إلى المستودع، فتنتقل مع الفريق ومع كل وكيل جديد، على عكس ذاكرة الأداة الشخصية المرتبطة بالجلسة.
حلقة تصحيح أقصر
أدوات السجلات وأخطاء المتصفح تتيح للوكيل قراءة الخطأ الفعلي بدل تخمينه من وصفك له.
قيمة تعليمية
للمطور الجديد على Laravel، رؤية الفرق بين الكود «الذي يعمل» والكود «الذي يتبع المعايير» في مشروع حقيقي تجربة تعليمية مكثّفة.

الحدود والاعتبارات الأمنية

Boost أداة تطوير محلية، وهذا ليس تفصيلًا شكليًا:

  • ثبّتها بـ --dev دائمًا، ولا تضعها في بيئة إنتاج.
  • أداة Database Query تنفّذ استعلامات فعلية على الاتصال المهيّأ. وجّهها إلى قاعدة بيانات تطوير، ولا تصل بها إلى بيانات مستخدمين حقيقية.
  • انتبه لما يخرج من جهازك: مخطط قاعدة بياناتك، وأسماء نماذجك، ومقتطفات سجلاتك قد تُرسل إلى مزوّد نموذج خارجي. راجع سياسة الاحتفاظ بالبيانات لدى الأداة التي تستخدمها، خصوصًا في المشاريع الخاضعة لالتزامات تعاقدية.
  • Boost يحسّن السياق، ولا يلغي المراجعة. الكود المولَّد يبقى مسؤوليتك: راجعه، واختبره، ولا تدمجه لمجرد أنه صار «يشبه أسلوب مشروعك».

الخلاصة

القيمة الحقيقية لـ Laravel Boost ليست في أنه «يفهم مشروعك» بشكل سحري، بل في أنه يفكك المشكلة إلى ثلاث طبقات واضحة: أدوات MCP تعطي الوكيل الحقائق الآنية عن تطبيقك، وتوجيهات ومهارات تعطيه معرفة الإطار المطابقة لإصدارك، وقواعد مشروع تعطيه أعراف فريقك.

ومن هذه الطبقات، الثالثة هي الأكثر إهمالًا والأعلى مردودًا. إن كنت ستفعل شيئًا واحدًا بعد التثبيت، فليكن تشغيل مهارة infer-conventions على مشروعك القائم ومراجعة ما تستخرجه. عندها فقط تصبح الأمثلة التي قرأتها أعلاه واقعًا يوميًا لا وعدًا تسويقيًا.