10 ممارسات نتبعها في داماتك لبناء أنظمة API آمنة وقابلة للتوسع

عشر ممارسات هندسية حقيقية من أنظمة إنتاج فعلية بنيناها في داماتك — من فصل صلاحيات النشر إلى ثغرات فعلية اكتشفناها وأصلحناها.

هذه ليست قائمة نظرية — إنها عشر ممارسات نطبّقها فعلياً في أنظمة الإنتاج التي نبنيها في داماتك، مأخوذة من قرارات حقيقية اتُّخذت أثناء بناء لوحات تحكم وأنظمة API تخدم مستخدمين فعليين.

1. الصلاحيات في الـ Middleware، لا داخل كل Controller

بدل تكرار if (!$user->can('...')) في كل دالة، اربط الصلاحية بمستوى المسار مباشرة: Route::post(...)->middleware('permission:articles.manage'). هذا يجعل خريطة الصلاحيات مقروءة بالكامل من ملف الروابط وحده، دون الحاجة لفتح كل Controller للتحقق.

2. افصل "من يستطيع الحفظ" عن "من يستطيع النشر"

ليست كل الإجراءات على المورد نفسه بنفس درجة الخطورة. في نظام إدارة محتوى، الفرق بين حفظ مسودة ونشرها فعلياً على الموقع فرق جوهري — يستحق صلاحية منفصلة (articles.manage مقابل articles.publish)، لا صلاحية واحدة تفتح كل شيء.

3. لا تثق بأن غياب حقل يعني "لا تغيير"

خطأ شائع: افتراض أن حقلاً غائباً من الطلب يعني تركه كما هو، بينما المنطق الفعلي يعيد توليده من حقول أخرى حاضرة. رأينا هذا الخطأ فعلياً يعيد كتابة رابط (Slug) مقال حي لمجرد أن طلباً جزئياً تضمّن العنوان دون الرابط نفسه. القاعدة: تحقّق من وجود الحقل المحدَّد صراحة ($request->has('slug'))، لا وجود حقول أخرى مرتبطة به منطقياً.

4. لا تفترض أن مكتبات PHP القياسية تدعم لغتك

str_word_count() في PHP لا يتعرّف على النصوص العربية إطلاقاً — يُرجع صفراً تقريباً لأي محتوى عربي بحت. أي حساب يعتمد على عدّ الكلمات (وقت القراءة، حدود المحتوى) في تطبيق متعدد اللغات يحتاج تقسيماً واعياً بترميز Unicode (preg_split('/\s+/u', ...)) لا دوال افتراضية مصمَّمة للنصوص اللاتينية فقط.

5. سجّل النشاط بأدنى بنية كافية، لا بمكتبة ثقيلة لكل شيء

ليست كل ميزة تستحق حزمة كاملة لتتبّع النشاط. جدول بسيط (article_id, user_id, action, meta, created_at) يغطي 90% من حاجة "من فعل ماذا ومتى" دون تعقيد إضافي — واحتفظ بالحزم الجاهزة للحالات التي تحتاج فعلاً ميزات متقدمة (استرجاع نسخ، مقارنة تغييرات تفصيلية).

6. اجعل التوليد التلقائي قابلاً للتجاوز دائماً

أي حقل يُولَّد تلقائياً (رابط SEO، وصف تعريفي، Slug) يجب أن يبقى قابلاً للتعديل اليدوي الكامل. التلقائية أداة مساعدة، لا قراراً نهائياً — المستخدم يجب أن يملك الكلمة الأخيرة دائماً.

7. الحد من معدل الطلبات (Rate Limiting) لكل نقطة نهاية بحسب حساسيتها

نقطة استعلام SQL مباشرة على قاعدة بيانات تستحق حداً أشد صرامة (throttle:5,1) من نقطة قراءة بسيطة (throttle:60,1). الحد الموحّد لكل الـ API سطحي — الحماية الفعلية تتناسب مع كلفة إساءة الاستخدام لكل نقطة تحديداً.

8. الحذف الناعم (Soft Delete) للمحتوى المنشور، الحذف الفعلي للبيانات المؤقتة

مقال نُشر واستُشهد به يستحق SoftDeletes — إمكانية استرجاعه إن حُذف بالخطأ. بيانات تتبّع مؤقتة (سجلات زيارات صفحة قديمة) لا تحتاج هذا العبء، بل حذفاً فعلياً دورياً يبقي الجدول بحجم معقول.

9. افحص التخزين المؤقت (Cache) للمسارات عند كل تعديل على الروابط

إضافة مسار جديد لا تعني أنه سيعمل فوراً إن كان تخزين الروابط مفعَّلاً في الإنتاج (route:cache). نسيان إعادة بناء هذا التخزين بعد كل تعديل روابط هو مصدر شائع لأخطاء "المسار غير موجود" التي تبدو غامضة دون سبب واضح.

10. اختبر المسار الفعلي، لا الافتراض النظري

الطريقة الوحيدة للتأكد من أن ميزة تعمل فعلاً هي تشغيلها على البيئة الحقيقية بعد كل تعديل — لا الاكتفاء بأن الكود "يبدو صحيحاً". فحص سريع عبر curl على المسار الفعلي بعد كل نشر يكشف أخطاء لا يكشفها القراءة البصرية للكود وحدها.