Repositories وخدمات نظيفة في Laravel 11 — SOLID بلا مبالغة
كل ما ستقرؤه هنا ناتج عن بناء عشرات الـ APIs لعملاء حقيقيين. الهدف ليس «تطبيق SOLID من أجل SOLID»، بل تحقيق شيئين: كود قابل للاختبار، وطبقات واضحة لا تختلط.الطبقات التي نعتمدهاRoute: اسم الـ endpoint + Middleware.FormReq…

كل ما ستقرؤه هنا ناتج عن بناء عشرات الـ APIs لعملاء حقيقيين. الهدف ليس «تطبيق SOLID من أجل SOLID»، بل تحقيق شيئين: كود قابل للاختبار، وطبقات واضحة لا تختلط.
الطبقات التي نعتمدها
- Route: اسم الـ endpoint + Middleware.
- FormRequest: تحقق من الإدخال فقط (بدون ترجمات أو منطق عمل).
- Controller: Try/Catch، يناول المدخلات للـ Service، ثمّ يغلّف النتيجة في Resource + Trait.
- Service: هنا يعيش منطق العمل. الـ Service وحده يُكلّم الـ Model.
- Resource: شكل الـ JSON النهائي — لا أكثر.
القاعدة الذهبيّة: المتحكم لا يعرف شيئًا عن Eloquent. الخدمة لا تعرف شيئًا عن HTTP.
ResponsesTrait ثابت على كل الـ APIs
نلفّ كل استجابة بنفس المغلف: { success, msg, data, meta? }. الواجهات الأمامية (Next.js) تعتمد هذا العقد بالضبط، فأي تغيير فيه يكسر الفرونت.
متى نبني Repository؟
لا نخترع Repositories بلا داعٍ. نضيفها فقط حين:
- منطق الاستعلام مكرّر في 3 أماكن أو أكثر.
- نحتاج واجهة (Interface) لاختبارها بـ fakes.
- نريد Cache layer موحّد دون تلويث الـ Service.
الـ Events وDomain Events
الخدمات تُطلق Events عوضًا عن استدعاء بعضها مباشرة. مثال: ProjectPublished يُنشّط Observer لمسح الكاش + إطلاق webhook إلى Next.js.
اختبار عملي
هدفنا أن يمكننا اختبار كل Service بدون ضرب قاعدة البيانات: نستبدل الـ Repository بـ fake في الحاوية، ثم نستدعي الـ Service مباشرة. Pest يجعل هذا ممتعًا.
ما لا نفعله
- لا نضع منطق العمل داخل Eloquent events (Model::saving).
- لا نستخدم facades عشوائيًا داخل Services (DI أوضح).
- لا نسمح للـ Controller بأن يلمس Model مباشرة.


