مقدمة في التوجيه
التوجيه هو الآلية التي تربط طلبات HTTP بكود محدد يتعامل مع تلك الطلبات. في لارافيل، تُعرَّف المسارات في ملفات موجودة في مجلد routes.
ما هو المسار؟ يحدد المسار كيفية استجابة تطبيقك لطلب HTTP محدد (GET، POST، PUT، DELETE، إلخ) إلى URI محدد. فكر في المسارات كنقاط الدخول إلى تطبيقك.
ملفات المسارات
يوفر لارافيل عدة ملفات مسارات لأغراض مختلفة:
- routes/web.php - لمسارات واجهة الويب (تشمل الجلسة، حماية CSRF، تشفير الكوكيز)
- routes/api.php - لمسارات API (بدون حالة، بدون جلسات)
- routes/console.php - لأوامر وحدة التحكم
- routes/channels.php - لقنوات البث
في هذا الدرس، سنركز على routes/web.php.
المسارات الأساسية
مسار GET بسيط
أبسط مسار في لارافيل يقبل URI ودالة closure:
// routes/web.php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return 'مرحباً بك في لارافيل!';
});
Route::get('/about', function () {
return 'صفحة من نحن';
});
Route::get('/contact', function () {
return 'اتصل بنا';
});
طرق التوجيه المتاحة
يوفر لارافيل طرقاً لجميع أفعال HTTP الشائعة:
Route::get($uri, $callback); // طلب GET
Route::post($uri, $callback); // طلب POST
Route::put($uri, $callback); // طلب PUT
Route::patch($uri, $callback); // طلب PATCH
Route::delete($uri, $callback); // طلب DELETE
Route::options($uri, $callback); // طلب OPTIONS
أفعال HTTP متعددة
أحياناً تحتاج إلى تسجيل مسار يستجيب لأفعال HTTP متعددة:
// الاستجابة لكل من GET و POST
Route::match(['get', 'post'], '/form', function () {
return 'هذا المسار يتعامل مع GET و POST';
});
// الاستجابة لجميع أفعال HTTP
Route::any('/any-method', function () {
return 'هذا المسار يتعامل مع أي فعل HTTP';
});
إرجاع العروض
بدلاً من إرجاع السلاسل، عادةً ما تُرجع العروض:
Route::get('/home', function () {
return view('home');
});
// تمرير البيانات إلى العروض
Route::get('/welcome', function () {
return view('welcome', [
'name' => 'أحمد محمد',
'role' => 'مطور'
]);
});
// استخدام دالة compact()
Route::get('/profile', function () {
$name = 'فاطمة علي';
$email = 'fatima@example.com';
return view('profile', compact('name', 'email'));
});
اختصار العرض: للمسارات التي تُرجع عرضاً فقط بدون منطق، يمكنك استخدام طريقة Route::view(): Route::view('/about', 'about', ['title' => 'من نحن']);
معاملات المسار
المعاملات المطلوبة
يمكنك التقاط أجزاء من URI باستخدام معاملات المسار:
// معامل واحد
Route::get('/users/{id}', function ($id) {
return "معرف المستخدم: " . $id;
});
// معاملات متعددة
Route::get('/posts/{postId}/comments/{commentId}', function ($postId, $commentId) {
return "المنشور: $postId, التعليق: $commentId";
});
// استخدام المعاملات مع العروض
Route::get('/articles/{id}', function ($id) {
return view('articles.show', ['articleId' => $id]);
});
المعاملات الاختيارية
اجعل المعاملات اختيارية بوضع ? بعد اسم المعامل وتوفير قيمة افتراضية:
Route::get('/users/{name?}', function ($name = 'ضيف') {
return "مرحباً، " . $name;
});
// معاملات اختيارية متعددة
Route::get('/posts/{category?}/{year?}', function ($category = 'الكل', $year = null) {
if ($year) {
return "المنشورات في $category من $year";
}
return "جميع المنشورات في $category";
});
قيود التعبيرات النمطية
قيّد معاملات المسار باستخدام طريقة where:
// يجب أن يكون المعرف رقمياً
Route::get('/users/{id}', function ($id) {
return "المستخدم: $id";
})->where('id', '[0-9]+');
// يجب أن يكون الاسم أبجدياً
Route::get('/users/{name}', function ($name) {
return "المستخدم: $name";
})->where('name', '[a-zA-Z]+');
// قيود متعددة
Route::get('/posts/{id}/{slug}', function ($id, $slug) {
return "المنشور $id: $slug";
})->where(['id' => '[0-9]+', 'slug' => '[a-z-]+']);
// استخدام طرق المساعدة
Route::get('/users/{id}', function ($id) {
return "المستخدم: $id";
})->whereNumber('id');
Route::get('/users/{name}', function ($name) {
return "المستخدم: $name";
})->whereAlpha('name');
Route::get('/posts/{slug}', function ($slug) {
return "المنشور: $slug";
})->whereAlphaNumeric('slug');
Route::get('/search/{term}', function ($term) {
return "البحث عن: $term";
})->whereIn('term', ['users', 'posts', 'comments']);
مهم: إذا لم يتطابق معامل المسار مع قيده، سيُرجع لارافيل استجابة 404 Not Found تلقائياً.
المسارات المسماة
تتيح لك المسارات المسماة إنشاء عناوين URL أو عمليات إعادة توجيه لمسارات محددة دون تضمين URI بشكل ثابت:
تعريف المسارات المسماة
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
Route::get('/user/profile', function () {
return view('profile');
})->name('profile');
Route::get('/posts/{id}', function ($id) {
return view('posts.show', compact('id'));
})->name('posts.show');
إنشاء عناوين URL للمسارات المسماة
// في المتحكمات أو العروض
$url = route('dashboard');
// تُرجع: http://yourapp.com/dashboard
$url = route('posts.show', ['id' => 5]);
// تُرجع: http://yourapp.com/posts/5
// مع معاملات الاستعلام
$url = route('posts.show', ['id' => 5, 'highlight' => 'comment-42']);
// تُرجع: http://yourapp.com/posts/5?highlight=comment-42
إعادة التوجيه إلى المسارات المسماة
// إعادة التوجيه إلى مسار مسمى
return redirect()->route('dashboard');
// مع المعاملات
return redirect()->route('posts.show', ['id' => 5]);
// مع بيانات flash
return redirect()
->route('dashboard')
->with('status', 'تم تحديث الملف الشخصي!');
استخدام المسارات المسماة في قوالب Blade
<!-- رابط بسيط -->
<a href="{{ route('dashboard') }}">لوحة التحكم</a>
<!-- مع المعاملات -->
<a href="{{ route('posts.show', ['id' => $post->id]) }}">
عرض المنشور
</a>
<!-- إجراء النموذج -->
<form action="{{ route('posts.store') }}" method="POST">
@csrf
<!-- حقول النموذج -->
</form>
أفضل ممارسة: استخدم دائماً المسارات المسماة بدلاً من تضمين عناوين URL بشكل ثابت. هذا يجعل تطبيقك أكثر قابلية للصيانة ويسمح لك بتغيير URIs دون كسر الروابط في تطبيقك.
مجموعات المسارات
تسمح لك مجموعات المسارات بمشاركة السمات عبر عدة مسارات:
مجموعات البادئة
// جميع المسارات ستحتوي على بادئة /admin
Route::prefix('admin')->group(function () {
Route::get('/users', function () {
// يطابق: /admin/users
});
Route::get('/posts', function () {
// يطابق: /admin/posts
});
});
بادئة الاسم
Route::name('admin.')->group(function () {
Route::get('/admin/users', function () {
// المسار المسمى: admin.users
})->name('users');
Route::get('/admin/posts', function () {
// المسار المسمى: admin.posts
})->name('posts');
});
مجموعات الوسيطات
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/dashboard', function () {
// يمكن الوصول إليه فقط للمستخدمين المصادق عليهم والمتحققين
});
Route::get('/profile', function () {
// يتطلب أيضاً auth و verified
});
});
دمج سمات المجموعة
Route::prefix('admin')
->name('admin.')
->middleware('auth')
->group(function () {
Route::get('/dashboard', function () {
// URI: /admin/dashboard
// الاسم: admin.dashboard
// الوسيطة: auth
})->name('dashboard');
Route::get('/users', function () {
// URI: /admin/users
// الاسم: admin.users
// الوسيطة: auth
})->name('users');
});
ربط نموذج المسار
يوفر ربط نموذج المسار حقناً تلقائياً لنسخ النموذج في مساراتك:
الربط الضمني
يحل لارافيل تلقائياً نماذج Eloquent المحددة في المسارات أو المتحكمات:
use App\Models\Post;
// حقن النموذج التلقائي
Route::get('/posts/{post}', function (Post $post) {
// يتم تحميل $post تلقائياً بناءً على المعرف في URL
return view('posts.show', compact('post'));
});
// إذا لم يكن المنشور بالمعرف المعطى موجوداً، يُرجع لارافيل 404
مفتاح مخصص للربط
افتراضياً، يستخدم لارافيل عمود id. يمكنك استخدام عمود مختلف:
// في نموذج Post الخاص بك (app/Models/Post.php)
public function getRouteKeyName()
{
return 'slug'; // استخدم slug بدلاً من id
}
// الآن يستخدم هذا المسار slug
Route::get('/posts/{post}', function (Post $post) {
// يحل بواسطة slug: /posts/my-first-post
return view('posts.show', compact('post'));
});
// أو حدد لكل مسار
Route::get('/posts/{post:slug}', function (Post $post) {
return view('posts.show', compact('post'));
});
الربط الصريح
حدد منطق الحل المخصص في RouteServiceProvider:
// app/Providers/RouteServiceProvider.php
use App\Models\Post;
use Illuminate\Support\Facades\Route;
public function boot()
{
Route::bind('post', function ($value) {
return Post::where('slug', $value)
->where('published', true)
->firstOrFail();
});
}
مسارات الموارد
تعيّن مسارات الموارد مسارات CRUD إلى متحكم بسطر واحد:
use App\Http\Controllers\PostController;
// ينشئ 7 مسارات لعمليات CRUD النموذجية
Route::resource('posts', PostController::class);
المسارات التي تم إنشاؤها بواسطة Resource
GET /posts index posts.index
GET /posts/create create posts.create
POST /posts store posts.store
GET /posts/{post} show posts.show
GET /posts/{post}/edit edit posts.edit
PUT/PATCH /posts/{post} update posts.update
DELETE /posts/{post} destroy posts.destroy
مسارات موارد جزئية
// إنشاء المسارات المحددة فقط
Route::resource('posts', PostController::class)->only([
'index', 'show'
]);
// إنشاء جميع المسارات باستثناء المحددة
Route::resource('posts', PostController::class)->except([
'create', 'store', 'destroy'
]);
مسارات موارد API
موارد API تستثني مسارات create وedit (التي تعرض نماذج HTML):
Route::apiResource('posts', PostController::class);
// ينشئ: index, store, show, update, destroy
الموارد المتداخلة
// المنشورات لديها العديد من التعليقات
Route::resource('posts.comments', CommentController::class);
// ينشئ مسارات مثل:
// GET /posts/{post}/comments
// POST /posts/{post}/comments
// GET /posts/{post}/comments/{comment}
// إلخ
تمرين عملي 1: المسارات الأساسية
أنشئ المسارات التالية في ملف routes/web.php الخاص بك:
- مسار GET لـ
/services يُرجع عرضاً يسمى 'services'
- مسار GET لـ
/pricing يُرجع النص "صفحة التسعير"
- مسار GET لـ
/blog يُرجع عرضاً مع البيانات: ['posts' => 25]
- اختبر جميع المسارات بزيارتها في متصفحك
تمرين عملي 2: معاملات المسار
أنشئ هذه المسارات مع المعاملات:
- مسار
/products/{id} حيث يجب أن يكون id رقمياً
- مسار
/categories/{name?} مع معامل اختياري (افتراضي: 'الكل')
- مسار
/search/{term}/{category?} مع معامل مطلوب واحد وآخر اختياري
- أضف قيوداً مناسبة لضمان أنواع البيانات
تمرين عملي 3: المسارات المسماة والمجموعات
تدرب على مجموعات المسارات:
- أنشئ مجموعة مسارات مع بادئة 'admin' تحتوي على 3 مسارات (dashboard، users، settings)
- امنح كل مسار اسماً مع بادئة 'admin.'
- أنشئ عناوين URL لهذه المسارات المسماة باستخدام دالة
route()
- أنشئ قالب Blade مع روابط باستخدام المسارات المسماة
عرض جميع المسارات
يوفر لارافيل أمراً مفيداً لعرض جميع المسارات المسجلة:
# عرض جميع المسارات
php artisan route:list
# عرض المسارات مع الوسيطات
php artisan route:list -v
# تصفية حسب الاسم
php artisan route:list --name=admin
# تصفية حسب URI
php artisan route:list --path=posts
# إظهار المسارات بتنسيق مضغوط
php artisan route:list --compact
التخزين المؤقت للمسارات
لأداء الإنتاج، قم بتخزين مساراتك مؤقتاً:
# تخزين المسارات مؤقتاً (تسجيل مسار أسرع)
php artisan route:cache
# مسح ذاكرة التخزين المؤقت للمسارات
php artisan route:clear
قيد التخزين المؤقت: لا يعمل التخزين المؤقت للمسارات مع المسارات القائمة على closure. إذا كنت تستخدم التخزين المؤقت للمسارات، يجب عليك تحويل جميع مسارات closure إلى طرق متحكم.
الملخص
في هذا الدرس، تعلمت:
- كيفية تعريف المسارات الأساسية مع أفعال HTTP المختلفة
- العمل مع معاملات المسار (مطلوبة، اختيارية، مع قيود)
- إنشاء واستخدام المسارات المسماة لعناوين URL قابلة للصيانة
- تنظيم المسارات مع مجموعات المسارات والبادئات
- تطبيق ربط نموذج المسار للحقن التلقائي للنموذج
- استخدام مسارات الموارد لعمليات CRUD RESTful
- عرض المسارات وتخزينها مؤقتاً لأداء أفضل
التوجيه هو أساس تطبيق لارافيل الخاص بك. في الدرس التالي، سنتعلم كيفية إنشاء متحكمات للتعامل مع منطق هذه المسارات!