← رجوع

فهم نظام الصلاحيات في Laravel باستخدام spatie/laravel-permission

R

UNIXMAN

Mar 12, 2026

Article Image

معظم الأنظمة تبدأ بفكرة بسيطة جدًا للصلاحيات: مستخدم عادي ومدير. في البداية يكفي شرط واحد داخل الكود:

if ($user->is_admin) {
    // allow
}

لكن هذا النوع من الحلول ينهار بسرعة مع توسع النظام. فجأة تظهر أسئلة مثل:

  • هل يمكن للمستخدم أن يكون لديه أكثر من دور؟
  • هل الصلاحيات مرتبطة بالدور أم بالمستخدم مباشرة؟
  • كيف يمكن تغيير الصلاحيات بدون تعديل الكود؟
  • كيف يمكن إدارة الصلاحيات من لوحة التحكم؟

هنا تظهر الحاجة إلى نظام صلاحيات مرن. مكتبة spatie/laravel-permission أصبحت من أكثر الحلول استخدامًا في Laravel لأنها تقدم طبقة جاهزة لإدارة الأدوار والصلاحيات دون إعادة اختراع النظام من الصفر.


الفكرة الأساسية للنظام

المكتبة مبنية على مفهومين رئيسيين:

  • Role
  • Permission

الصلاحية تمثل فعلًا محددًا في النظام مثل:

  • create-post
  • edit-post
  • delete-user

أما الدور فهو مجموعة من الصلاحيات.

مثلًا:

  • admin
  • editor
  • author

الفكرة أن المستخدم يمكن أن يمتلك:

  • دورًا
  • أو عدة أدوار
  • أو صلاحيات مباشرة بدون دور

هيكل قاعدة البيانات الذي تنشئه المكتبة

عند تثبيت المكتبة يتم إنشاء عدة جداول.

أهمها:

  • roles
  • permissions
  • model_has_roles
  • model_has_permissions
  • role_has_permissions

هذا التصميم يسمح بعلاقات متعددة بين المستخدمين والأدوار والصلاحيات.

بنية العلاقات تقريبًا تكون كالتالي:

  • المستخدم يمكن أن يمتلك عدة أدوار
  • الدور يمكن أن يمتلك عدة صلاحيات
  • المستخدم يمكن أن يمتلك صلاحيات مباشرة

وهذا يعني أن النظام يدعم:

  • Many to Many relations

إضافة Trait إلى نموذج المستخدم

لكي يعمل النظام يجب إضافة trait إلى نموذج المستخدم:

use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
}

هذا الـ Trait يضيف عدة وظائف للنموذج مثل:

  • assignRole
  • givePermissionTo
  • hasRole
  • hasPermissionTo

ويوفر أيضًا علاقات Eloquent جاهزة.


إنشاء الأدوار والصلاحيات

يمكن إنشاء الصلاحيات مباشرة عبر الكود:


use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

Permission::create(['name' => 'edit posts']);

Role::create(['name' => 'admin']);

بعد ذلك يمكن ربط الصلاحيات بالدور:


$role = Role::findByName('admin');
$role->givePermissionTo('edit posts');

أو إعطاء صلاحية مباشرة للمستخدم:


$user->givePermissionTo('edit posts');

إسناد الأدوار للمستخدم

ربط الدور بالمستخدم يتم ببساطة:


$user->assignRole('admin');

يمكن أيضًا إسناد عدة أدوار:


$user->assignRole(['admin','editor']);

المكتبة تتكفل بإدارة العلاقة داخل جدول:

model_has_roles

التحقق من الصلاحيات

التحقق يمكن أن يتم بعدة طرق.

التحقق من الدور


if ($user->hasRole('admin')) {
    //
}

التحقق من الصلاحية


if ($user->can('edit posts')) {
    //
}

المكتبة تتكامل مباشرة مع نظام authorization في Laravel.


استخدام Middleware

يمكن حماية المسارات بسهولة.


Route::get('/admin', function () {
    //
})->middleware('role:admin');

أو باستخدام الصلاحيات:


Route::get('/posts', function () {
    //
})->middleware('permission:edit posts');

بهذا الشكل يصبح نظام الحماية جزءًا من طبقة التوجيه.


التخزين المؤقت للصلاحيات

أحد التفاصيل المهمة في المكتبة هو استخدام cache للصلاحيات.

السبب بسيط: التحقق من الصلاحيات يحدث كثيرًا أثناء الطلب.

لذلك تقوم المكتبة بتخزين الصلاحيات في cache لتقليل الاستعلامات.

عند تغيير الصلاحيات يجب مسح الكاش:


php artisan permission:cache-reset

المشاكل الشائعة عند استخدام المكتبة

الخلط بين الدور والصلاحية

الدور ليس بديلاً للصلاحية.

الدور مجرد مجموعة صلاحيات.

إنشاء صلاحيات كثيرة جدًا

بعض الأنظمة تنشئ صلاحية لكل زر داخل التطبيق.

هذا يجعل النظام معقدًا جدًا في الإدارة.

عدم التفكير في الصلاحيات أثناء تصميم النظام

إضافة نظام الصلاحيات بعد بناء النظام غالبًا يؤدي إلى مشاكل.

الأفضل التفكير في:

  • الأدوار الأساسية
  • الصلاحيات الرئيسية
  • علاقة الصلاحيات بالموارد
من البداية.


متى لا تكون هذه المكتبة كافية

في الأنظمة الكبيرة قد تحتاج إلى ما يسمى:

  • ACL
  • Attribute Based Access Control

حيث تعتمد الصلاحية على:

  • المستخدم
  • المورد
  • السياق

مثل:

  • المستخدم يمكنه تعديل مقالاته فقط

في هذه الحالة يتم دمج المكتبة مع Policies الخاصة بـ Laravel.