كيفية تحديد نوع المستخدم isAdmin في Laravel وحماية صفحات لوحة الإدارة
في معظم تطبيقات Laravel لا يكفي أن نعرف أن المستخدم قام بتسجيل الدخول فقط، بل نحتاج في كثير من الأحيان إلى تحديد ما الذي يُسمح لهذا المستخدم بالوصول إليه بعد تسجيل الدخول.
على سبيل المثال، قد يحتوي التطبيق على نوعين من المستخدمين:
- User: مستخدم عادي يمكنه الوصول إلى لوحة المستخدم وصفحاته الخاصة.
- Admin: مدير يمكنه بالإضافة إلى ذلك الوصول إلى لوحة الإدارة وإدارة المستخدمين والمحتوى والإعدادات.
هنا يظهر الفرق بين مفهومين أساسيين في Laravel:
- Authentication: التحقق من هوية المستخدم ومعرفة هل قام بتسجيل الدخول أم لا.
- Authorization: تحديد الصلاحيات التي يمتلكها المستخدم بعد تسجيل الدخول.
في هذا الدليل سننشئ نظاماً بسيطاً وعملياً لتحديد المستخدم المدير باستخدام حقل is_admin داخل جدول users، ثم سننشئ Middleware يمنع المستخدمين العاديين من الوصول إلى صفحات الإدارة.
كما سنتعرف على استخدام Blade Directives وGates، ومتى يجب الانتقال من حقل is_admin البسيط إلى نظام Roles & Permissions متكامل.
ما الفرق بين Authentication وAuthorization في Laravel؟
من الأخطاء الشائعة اعتبار تسجيل الدخول والصلاحيات شيئاً واحداً.
عندما يستخدم Laravel Middleware مثل:
auth
فهو يتحقق فقط من أن المستخدم قام بتسجيل الدخول.
لكنه لا يحدد ما إذا كان هذا المستخدم مديراً أو موظفاً أو مستخدماً عادياً.
على سبيل المثال، قد يكون لدينا المستخدمان التاليان:
| User | Authenticated | Admin |
|---|---|---|
| Ahmad | Yes | No |
| Mohammad | Yes | Yes |
كلا المستخدمين مسجلان للدخول، وبالتالي كلاهما ينجح مع:
middleware('auth')
لكن Mohammad فقط يجب أن يستطيع الدخول إلى:
/admin
وهنا نحتاج إلى Authorization إضافية تحدد من هو Admin.
فكرة نظام is_admin
سنضيف عموداً Boolean إلى جدول users باسم:
is_admin
وستكون القيم:
| القيمة | نوع المستخدم |
|---|---|
| 0 / false | مستخدم عادي |
| 1 / true | Admin |
بعد ذلك سنقوم بإنشاء Middleware يتحقق من هذا الحقل قبل السماح للطلب بالوصول إلى صفحات الإدارة.
User
│
▼
Login
│
▼
auth Middleware
│
├── Not Authenticated → Login
│
▼
Admin Middleware
│
├── is_admin = false → 403 Forbidden
│
▼
is_admin = true
│
▼
Admin Dashboard
1. تجهيز نظام تسجيل الدخول
يجب أولاً أن يكون لديك نظام Authentication داخل التطبيق.
في إصدارات Laravel القديمة كان من الشائع استخدام Laravel Breeze:
composer require laravel/breeze --dev
php artisan breeze:install
php artisan migrate
npm install
npm run dev
أما إذا كان لديك مشروع قديم يستخدم Breeze بالفعل، فلا يؤثر ذلك على فكرة is_admin التي سنشرحها؛ فالآلية تعتمد على نظام Authentication الأساسي في Laravel وليس على Breeze تحديداً.
2. إضافة حقل is_admin إلى جدول users
لا ينبغي تعديل Migration قديم تم تشغيله على بيئة Production، بل الأفضل إنشاء Migration جديد يضيف الحقل.
نفذ:
php artisan make:migration add_is_admin_to_users_table --table=users
سيتم إنشاء Migration جديد داخل:
database/migrations
قم بتعديله إلى:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('is_admin')
->default(false);
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('is_admin');
});
}
};
لماذا نستخدم default(false)؟
من المهم جداً عدم إنشاء الحقل بهذه الصورة فقط:
$table->boolean('is_admin');
والأفضل:
$table->boolean('is_admin')
->default(false);
لأن أي مستخدم جديد يتم تسجيله يجب أن يكون مستخدماً عادياً بشكل افتراضي.
أي أن:
is_admin = false
هي الحالة الافتراضية الآمنة.
ولا يتم منح صلاحية Admin إلا بشكل صريح.
3. تنفيذ Migration
بعد إنشاء Migration نفذ:
php artisan migrate
سيصبح جدول users مثلاً:
| id | name | password | is_admin | |
|---|---|---|---|---|
| 1 | Ahmad | ahmad@example.com | ... | 0 |
| 2 | Mohammad | mohammad@example.com | ... | 1 |
المستخدم رقم 1 مستخدم عادي، بينما المستخدم رقم 2 Admin.
4. إضافة Cast لحقل is_admin داخل User Model
من الأفضل إخبار Eloquent أن حقل is_admin عبارة عن Boolean.
افتح:
app/Models/User.php
ثم أضف Cast للحقل.
في Laravel الحديث يمكن استخدام:
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
'is_admin' => 'boolean',
];
}
وبالتالي عندما نستخدم:
$user->is_admin
سيتعامل Laravel معها كقيمة:
true
أو:
false
بدلاً من الاعتماد على القيمة الرقمية القادمة من قاعدة البيانات.
5. إنشاء Admin Middleware
نقوم الآن بإنشاء Middleware مسؤول عن التحقق من أن المستخدم Admin.
نفذ:
php artisan make:middleware AdminMiddleware
سيقوم Laravel بإنشاء:
app/Http/Middleware/AdminMiddleware.php
6. كتابة AdminMiddleware
افتح الملف وأضف:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class AdminMiddleware
{
public function handle(Request $request, Closure $next): Response
{
if (!$request->user() || !$request->user()->is_admin) {
abort(403, 'Unauthorized action.');
}
return $next($request);
}
}
كيف يعمل AdminMiddleware؟
نستخدم:
$request->user()
للحصول على المستخدم الحالي.
ثم نتحقق من حالتين:
if (!$request->user() || !$request->user()->is_admin)
أي:
- هل يوجد مستخدم قام بتسجيل الدخول؟
- هل قيمة
is_adminلديه تساوي true؟
إذا لم يتحقق أحد الشرطين يتم تنفيذ:
abort(403);
وسيتم إرجاع HTTP Status:
403 Forbidden
أما إذا كان المستخدم Admin فيتم تمرير الطلب:
return $next($request);
لماذا نستخدم $request->user() بدلاً من auth()->user()؟
الطريقتان تعملان في هذا السيناريو:
auth()->user()
و:
$request->user()
لكن استخدام المستخدم المرتبط بالـ Request يجعل Middleware واضحاً ومباشراً، ويجنبنا كذلك محاولة قراءة خاصية is_admin من قيمة null إذا وصل الطلب بدون مستخدم مصادق عليه.
7. تسجيل Middleware في Laravel الحديث
هذه من أهم النقاط التي تختلف بين إصدارات Laravel.
Laravel 11 وما بعده
في البنية الحديثة يتم تسجيل Middleware aliases داخل:
bootstrap/app.php
أولاً قم باستيراد Middleware:
use App\Http\Middleware\AdminMiddleware;
use Illuminate\Foundation\Configuration\Middleware;
ثم:
->withMiddleware(function (Middleware $middleware): void {
$middleware->alias([
'admin' => AdminMiddleware::class,
]);
})
ويكون جزء من الملف مثلاً:
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use App\Http\Middleware\AdminMiddleware;
return Application::configure(
basePath: dirname(__DIR__)
)
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware): void {
$middleware->alias([
'admin' => AdminMiddleware::class,
]);
})
->withExceptions(function (Exceptions $exceptions): void {
//
})
->create();
أصبح لدينا الآن Middleware alias باسم:
admin
Laravel 10 والإصدارات القديمة
إذا كنت تعمل على Laravel 10 أو إصدار أقدم، ستجد تسجيل Middleware عادة داخل:
app/Http/Kernel.php
مثلاً:
protected $middlewareAliases = [
'admin' => \App\Http\Middleware\AdminMiddleware::class,
];
8. حماية صفحة Admin
بعد تسجيل Middleware يمكننا استخدامه داخل:
routes/web.php
مثلاً:
use Illuminate\Support\Facades\Route;
Route::get('/admin', function () {
return view('admin');
})->middleware(['auth', 'admin'])
->name('admin');
لاحظ أننا استخدمنا:
['auth', 'admin']
وليس admin فقط.
Middleware الأول:
auth
يتأكد أن المستخدم قام بتسجيل الدخول.
أما:
admin
فيتحقق من صلاحية الإدارة.
9. حماية مجموعة كاملة من Admin Routes
عادة لا تحتوي لوحة الإدارة على Route واحد فقط.
قد يكون لدينا:
/admin
/admin/users
/admin/posts
/admin/settings
/admin/reports
بدلاً من إضافة Middleware لكل Route بشكل منفصل، يمكن استخدام Route Group:
Route::middleware(['auth', 'admin'])
->prefix('admin')
->name('admin.')
->group(function () {
Route::get('/', function () {
return view('admin.dashboard');
})->name('dashboard');
Route::get('/users', function () {
return view('admin.users');
})->name('users');
Route::get('/settings', function () {
return view('admin.settings');
})->name('settings');
});
ميزة استخدام prefix
عند استخدام:
->prefix('admin')
لا نحتاج إلى كتابة /admin في كل Route.
فمثلاً:
Route::get('/users', ...);
سيصبح عنوانه فعلياً:
/admin/users
ميزة استخدام name prefix
استخدام:
->name('admin.')
يعني أن:
->name('users')
سيصبح:
admin.users
ويمكن استدعاؤه:
route('admin.users')
10. فصل صفحات المستخدم عن صفحات الإدارة
يمكن أن يكون لدينا Dashboard متاحة لجميع المستخدمين المسجلين:
Route::middleware('auth')->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
});
ثم Routes إضافية للإدارة:
Route::middleware(['auth', 'admin'])
->prefix('admin')
->name('admin.')
->group(function () {
Route::get('/', function () {
return view('admin.dashboard');
})->name('dashboard');
});
النتيجة:
| Route | User | Admin |
|---|---|---|
| /dashboard | ✓ | ✓ |
| /admin | ✗ | ✓ |
11. إخفاء روابط Admin من Blade
من الطبيعي ألا نريد إظهار رابط لوحة الإدارة للمستخدم العادي.
داخل Blade يمكن استخدام:
@auth
@if(auth()->user()->is_admin)
<a href="{{ route('admin.dashboard') }}">
Admin Dashboard
</a>
@endif
@endauth
أو باستخدام المستخدم المرتبط بالطلب:
@if(auth()->check() && auth()->user()->is_admin)
<a href="{{ route('admin.dashboard') }}">
Admin Dashboard
</a>
@endif
إخفاء الرابط ليس حماية أمنية
هذه نقطة مهمة جداً.
الكود:
@if(auth()->user()->is_admin)
يستخدم فقط لتحديد ما الذي سيظهر في واجهة المستخدم.
لكنه ليس بديلاً عن Middleware.
فحتى لو أخفينا الرابط، يمكن للمستخدم كتابة:
https://example.com/admin
يدوياً في المتصفح.
الحماية الحقيقية يجب أن تكون على السيرفر:
->middleware(['auth', 'admin'])
12. إضافة دالة isAdmin إلى User Model
يمكن جعل الكود أكثر وضوحاً بإضافة Method داخل User Model:
public function isAdmin(): bool
{
return $this->is_admin;
}
ثم يصبح Middleware:
if (!$request->user() || !$request->user()->isAdmin()) {
abort(403);
}
وكذلك داخل التطبيق:
if ($user->isAdmin()) {
// Admin
}
هذا يفصل منطق تحديد الإدارة عن بقية أجزاء التطبيق ويسهل تعديله مستقبلاً.
13. إنشاء أول Admin
يمكن تعديل المستخدم مباشرة باستخدام Laravel Tinker.
شغّل:
php artisan tinker
ثم:
$user = App\Models\User::find(1);
$user->is_admin = true;
$user->save();
أو:
App\Models\User::where('email', 'admin@example.com')
->update([
'is_admin' => true,
]);
14. لا تسمح للمستخدم بتحديد is_admin أثناء التسجيل
من الأخطاء الأمنية الخطيرة إضافة:
is_admin
إلى نموذج Registration العام وقراءة قيمته مباشرة من Request.
لا تستخدم مثلاً:
User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
'is_admin' => $request->is_admin,
]);
لأن المستخدم يستطيع تعديل HTTP Request يدوياً وإرسال:
is_admin=1
وبذلك قد يمنح نفسه صلاحيات Admin إذا لم توجد طبقات تحقق أخرى.
الأفضل أثناء التسجيل:
User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
ويترك:
is_admin = false
وفق القيمة الافتراضية في قاعدة البيانات.
15. استخدام Gate بدلاً من Middleware مخصص
Laravel يحتوي على نظام Authorization مدمج يسمى Gates وPolicies.
لحالة بسيطة مثل السماح بالدخول إلى Admin Dashboard يمكن إنشاء Gate.
مثلاً داخل Service Provider:
use App\Models\User;
use Illuminate\Support\Facades\Gate;
public function boot(): void
{
Gate::define('access-admin', function (User $user) {
return $user->is_admin;
});
}
بعد ذلك يمكن حماية Route:
Route::get('/admin', function () {
return view('admin');
})->middleware(['auth', 'can:access-admin']);
Middleware:
can:access-admin
سيطلب من Laravel التحقق من الـ Gate قبل السماح بالوصول إلى الصفحة.
16. استخدام Gate داخل Blade
ميزة Gates أنها تتكامل مباشرة مع Blade.
يمكن استخدام:
@can('access-admin')
<a href="{{ route('admin.dashboard') }}">
Admin Dashboard
</a>
@endcan
بدلاً من تكرار:
@if(auth()->user()->is_admin)
في أكثر من مكان.
Middleware أم Gate؟
كلا الحلين صحيح، لكن لكل منهما استخدام مناسب.
| الحالة | الخيار المناسب |
|---|---|
| منع المستخدم غير الإداري من قسم كامل | Middleware |
| صلاحية عامة مثل Access Admin | Gate |
| صلاحيات مرتبطة بـ Model مثل تعديل Post | Policy |
| نظام Roles وصلاحيات معقد | Roles & Permissions |
17. استخدام Policies للصلاحيات المرتبطة بالبيانات
لنفرض أن المستخدم يستطيع الدخول إلى لوحة الإدارة، لكن ليس كل Admin يجب أن يكون قادراً على حذف Posts.
هنا يصبح الحقل:
is_admin
غير كافٍ للتعبير عن جميع الصلاحيات.
يمكن استخدام Laravel Policies لتنظيم صلاحيات مثل:
view
create
update
delete
restore
forceDelete
على Models معينة.
مثلاً:
php artisan make:policy PostPolicy --model=Post
ثم داخل Policy يمكن تحديد من يستطيع حذف Post:
public function delete(User $user, Post $post): bool
{
return $user->is_admin;
}
18. متى لا يكون is_admin كافياً؟
حقل Boolean مناسب عندما يكون النظام بسيطاً جداً:
User
Admin
لكن تخيل تطبيقاً يحتوي على:
Super Admin
Admin
Manager
Editor
Support
Accountant
User
وصلاحيات مثل:
view users
create users
edit users
delete users
view reports
export reports
edit settings
view invoices
create invoices
refund invoices
في هذه الحالة إنشاء حقول:
is_admin
is_manager
is_editor
is_support
is_accountant
ليس تصميماً جيداً وقابلاً للتوسع.
الأفضل بناء نظام:
Users
│
▼
Roles
│
▼
Permissions
بحيث يمكن إعطاء المستخدم Role واحداً أو أكثر وكل Role يحتوي مجموعة Permissions.
19. is_admin أم role؟
هناك طريقة أخرى بسيطة وهي استخدام حقل:
role
مثلاً:
user
admin
manager
بدلاً من:
is_admin
حقل is_admin ممتاز عندما لا يوجد إلا حالتان:
Admin
Not Admin
أما إذا كان التطبيق يحتوي عدة أنواع من المستخدمين، فإن Role أو نظام Roles & Permissions سيكون أكثر مرونة.
20. إرجاع 403 أم إعادة التوجيه؟
في Middleware استخدمنا:
abort(403);
وهذا هو السلوك الصحيح أمنياً عندما يكون المستخدم Authenticated لكنه لا يملك الصلاحية.
الفرق:
| Status | المعنى |
|---|---|
| 401 Unauthorized | لم تتم المصادقة على المستخدم |
| 403 Forbidden | المستخدم معروف لكنه لا يملك الصلاحية المطلوبة |
لذلك المستخدم الذي قام بتسجيل الدخول ولكنه ليس Admin يناسبه:
403 Forbidden
21. تخصيص صفحة خطأ 403
بدلاً من عرض صفحة Laravel الافتراضية يمكن إنشاء:
resources/views/errors/403.blade.php
مثلاً:
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<title>غير مصرح لك بالدخول</title>
</head>
<body>
<main>
<h1>403</h1>
<h2>غير مصرح لك بالدخول إلى هذه الصفحة</h2>
<p>
لا يمتلك حسابك الصلاحيات المطلوبة للوصول إلى هذا القسم.
</p>
<a href="{{ route('dashboard') }}">
العودة إلى لوحة التحكم
</a>
</main>
</body>
</html>
22. Middleware الكامل
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class AdminMiddleware
{
public function handle(
Request $request,
Closure $next
): Response {
if (
!$request->user() ||
!$request->user()->is_admin
) {
abort(403);
}
return $next($request);
}
}
23. User Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
protected $fillable = [
'name',
'email',
'password',
];
protected $hidden = [
'password',
'remember_token',
];
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
'is_admin' => 'boolean',
];
}
public function isAdmin(): bool
{
return $this->is_admin;
}
}
24. نقطة أمنية مهمة حول $fillable
لاحظ أننا لم نضع:
is_admin
ضمن:
$fillable
في هذا المثال.
السبب أن جعل الحقل Mass Assignable دون الحاجة إليه قد يزيد خطر تعيينه عن طريق الخطأ في عمليات مثل:
User::create($request->all());
أو:
$user->update($request->all());
يفضل دائماً تحديد الحقول المسموح للمستخدم بتعديلها بشكل صريح وعدم تمرير كل محتويات Request مباشرة إلى Model.
25. Routes كاملة
<?php
use Illuminate\Support\Facades\Route;
Route::middleware('auth')->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
});
Route::middleware(['auth', 'admin'])
->prefix('admin')
->name('admin.')
->group(function () {
Route::get('/', function () {
return view('admin.dashboard');
})->name('dashboard');
Route::get('/users', function () {
return view('admin.users');
})->name('users');
Route::get('/settings', function () {
return view('admin.settings');
})->name('settings');
});
26. التسلسل الكامل لطلب Admin
عندما يزور المستخدم:
/admin
يمر الطلب بالتسلسل التالي:
Browser
│
▼
GET /admin
│
▼
auth Middleware
│
├── Guest
│ └── Redirect to Login
│
▼
Authenticated User
│
▼
AdminMiddleware
│
├── is_admin = false
│ └── 403 Forbidden
│
▼
is_admin = true
│
▼
Route / Controller
│
▼
Admin View
وبذلك لدينا طبقتان منفصلتان:
Authentication
+
Authorization
27. أخطاء شائعة في نظام is_admin
حماية الرابط في Blade فقط
إخفاء رابط Admin ليس حماية. يجب حماية Route على السيرفر.
عدم استخدام auth Middleware
إذا افترض Middleware دائماً وجود مستخدم ثم استخدمت:
auth()->user()->is_admin
فقد تواجه خطأ إذا كان المستخدم Guest.
السماح بتعديل is_admin من Profile
لا تسمح للمستخدم بإرسال is_admin ضمن بيانات تحديث حسابه.
جعل المستخدم Admin أثناء التسجيل بناء على Request
هذه ثغرة صلاحيات خطيرة ويجب تجنبها.
استخدام is_admin لنظام صلاحيات ضخم
عندما تتعدد أنواع المستخدمين والصلاحيات، انتقل إلى Roles وPermissions أو Policies.
استخدام Kernel.php في مشروع Laravel حديث
الشروحات القديمة تسجل Middleware aliases داخل app/Http/Kernel.php، بينما تستخدم بنية Laravel الحديثة bootstrap/app.php.
28. تحسين إضافي: إضافة verified
إذا كنت تريد السماح للإدارة فقط للمستخدمين الذين أكدوا بريدهم الإلكتروني، يمكن إضافة:
verified
فتصبح المجموعة:
Route::middleware([
'auth',
'verified',
'admin'
])->group(function () {
// Admin routes
});
وبذلك يجب أن يكون المستخدم:
- مسجل الدخول.
- أكد البريد الإلكتروني.
- يمتلك صلاحية Admin.
29. هل is_admin نظام آمن؟
نعم، استخدام Boolean مثل is_admin يمكن أن يكون حلاً آمناً ومناسباً إذا كان التطبيق يحتاج فقط إلى التمييز بين:
User
Admin
الأمان لا يعتمد على اسم الحقل، بل على طريقة تطبيق Authorization.
يجب أن يكون التحقق من الصلاحية على السيرفر، وألا يستطيع المستخدم تعديل قيمة is_admin بنفسه، وأن تتم حماية جميع Admin Routes باستخدام Middleware أو Gate أو Policy مناسب.
30. ما التصميم الذي يجب استخدامه؟
يمكن تلخيص الاختيار بالشكل التالي:
| حجم النظام | التصميم المناسب |
|---|---|
| User / Admin فقط | is_admin Boolean |
| عدة أنواع مستخدمين بسيطة | role |
| صلاحيات على Models | Laravel Policies |
| صلاحيات عامة | Laravel Gates |
| نظام إداري كبير | Roles & Permissions |
الخلاصة
تسجيل الدخول في Laravel لا يعني أن المستخدم يمتلك حق الوصول إلى جميع أجزاء التطبيق. يقوم Authentication بإثبات هوية المستخدم، بينما تقوم Authorization بتحديد ما يستطيع هذا المستخدم القيام به.
عندما يكون التطبيق بسيطاً ويحتوي على مستخدم عادي ومدير فقط، فإن إضافة حقل Boolean باسم:
is_admin
إلى جدول users تعتبر طريقة بسيطة وفعالة.
البنية الكاملة تصبح:
users.is_admin
│
▼
User Model Cast
│
▼
Authentication
│
▼
Admin Middleware
│
▼
Protected Admin Routes
│
▼
Admin Dashboard
أما إذا تطور التطبيق وأصبح يحتوي على أنواع متعددة من المستخدمين وصلاحيات مختلفة، فمن الأفضل عدم إضافة المزيد من حقول Boolean، بل الانتقال إلى Laravel Gates وPolicies أو بناء نظام Roles & Permissions متكامل.
وأياً كان التصميم المستخدم، يجب تطبيق قاعدة أساسية: لا تعتمد على إخفاء الأزرار أو الروابط في الواجهة كوسيلة للحماية، بل يجب تنفيذ التحقق من الصلاحيات دائماً على السيرفر قبل تنفيذ العملية أو عرض المورد المحمي.
جزاك الله خيرا شرح مبسط ومفهوم
وجزاك الله خيرًا، شكرًا جزيلًا على متابعتك.
شكرا كتير عالمعلومات القيمة والشرح المبسط
لو امكن حضرتك تعرفنا الطرق الاخري زي ان يبقي في جدول خاص بالادمن مثلا والصلاحيات .. شكر جزيلا