سبد خرید

ایجاد route در لاراول به صورت بهینه

ایجاد route در لاراول به صورت بهینه

در این مقاله بهترین حالت تعرف کردن و گروه بندی route ها در لاراول رو بررسی میکنیم . این به شما کمک میکنه ورود و end-point های پروژتون رو با ساختاری درست و بهینه توسعه بدید laravel route بخشی هست که شما از همون ابتدای یادگیری و استفاده از لاراول زیاد ازش استفاده می‌کنید و اگر نحوه درست نوشتن route ها رو بلد نباشید حجم کد های پروژه که یکم مقدار زیاد بشه قطعا به مشکل می‌خورید ، پس این مقاله رو اصلا از دست ندید

route یا end-point در لاراول چیست؟

آدرس های ورودی به پروژه لاراول توسط route ها تعیین میشه و چه به صورت web route و یا api route شما url های ورودی پروژتون رو در این قسمت تعیین می‌کنید . به عنوان مثال آدرس bitcode1.com/aboutus یک route داره که از نوع GET و با نام aboutus هست ، که با فراخانی این آدرس یک view که محتوای صفحه درباره ما هست برمیگرده.

گروه بندی route ها با استفاده از route::resource و route::apiResource

این مورد شناخته شده ترین روش برای گروه بندی route های لاراول هست . با یک مثال به صورت کامل این مورد رو یاد میگیرید . فرض کنید ما میخوایم این تعداد route رو تعریف کنیم

Route::get('books', [BookController::class, 'index'])->name('books.index');
Route::get('books/create', [BookController::class, 'create'])->name('books.create');
Route::post('books', [BookController::class, 'store'])->name('books.store');
Route::get('books/{book}', [BookController::class, 'show'])->name('books.show');
Route::get('books/{book}/edit', [BookController::class, 'edit'])->name('books.edit');
Route::put('books/{book}', [BookController::class, 'update'])->name('books.update');
Route::delete('books/{book}', [BookController::class, 'destroy'])->name('books.destroy');

با استفاده از route::resource و route::apiResource این موارد خیلی ساده میشه به صورت زیر

Route::resource('books', BookController::class);

و اگر میخواید API route تعریف کنید به صورت زیر میشه که البته 5 تا route بیشتر ایجاد نمیکنه

Route::apiResource('books', BookController::class);

یا حتی اگر فقط 2 یا 3 تا از موارد resource رو نیاز دارید هم میتونید به این صورت محدودش کنید

// Instead, here names "books.create" and "books.store" are assigned automatically

Route::resource('books', BookController::class)->only(['create', 'store']);

استفاده از group برای ایجاد تعدادی route با یک سری ویژگی ها مشترک خیلی کاربردی هست و حجم کد ها رو کاهش میده مثال زیر رو با دقت ببینید

Route::middleware('auth')->group(function() {
 
    Route::middleware('is_admin')->prefix('admin')->group(function() {
    	Route::get(...) // administrator routes
    });
 
    Route::middleware('is_user')->prefix('user')->group(function() {
    	Route::get(...) // user routes
    });
});

حالا اگر تعداد middleware هایی که داریم زیاده تکلیف چیه؟

فرض کنید route های شما دارای تعداد زیادی از middleware هستن مثل کد های زیر

Route::prefix('students')->middleware(['auth', 'check.role', 'check.user.status', 'check.invoice.status', 'locale'])->group(function () {
    // ... student routes
});
 
Route::prefix('managers')->middleware(['auth', 'check.role', 'check.user.status', 'locale'])->group(function () {
    // ... manager routes
});

در این صورت میریم سراغ فایل app/Http/Kernel.php و همه این middleware ها رو به صورت middlewareGroups تعریف میکنیم . این شکلی :

protected $middlewareGroups = [
    // This group comes from default Laravel
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
 
    // This group comes from default Laravel
    'api' => [
        // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        'throttle:api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
 
    // THIS IS OUR NEW MIDDLEWARE GROUP
    'check_user' => [
        'auth',
        'check.role',
        'check.user.status',
        'locale'
    ],
];

این کار رو که انجام بدیم حالا همه middleware ها رو در check_user داریم و میتونیم route ها رو این شکلی بازنویسی کنیم :

Route::prefix('students')->middleware(['check_user', 'check.invoice.status'])->group(function () {
    // ... student routes
});
 
Route::prefix('managers')->middleware(['check_user'])->group(function () {
    // ... manager routes
});

نحوه اضافه کردن فایل جدید برای route ها در لاراول

به صورت پیشفرض دو فایل api.php و web.php برای تعریف کردن route ها در لاراول وجود داره ، حالا اگر بخوایم یک فایل دیگه اضافه کنیم باید چیکار کرد ؟ اول باید این فایل رو باز کنیم app/Providers/RouteServiceProvider.php که محتوای پیشفرضش به شکل زیر هست

public function boot()
{
    $this->configureRateLimiting();
 
    $this->routes(function () {
        Route::middleware('api')
            ->prefix('api')
            ->group(base_path('routes/api.php'));
 
        Route::middleware('web')
            ->group(base_path('routes/web.php'));
    });
}

حالا ما میخوایم فایل admin.php رو هم اضافه کنید که route های مربوط به بخش ادمین کاملا جدا باشه

$this->routes(function () {
    Route::middleware('api')
        ->prefix('api')
        ->group(base_path('routes/api.php'));
 
    Route::middleware('web')
        ->group(base_path('routes/web.php'));
 
    Route::middleware('is_admin')
        ->group(base_path('routes/admin.php'));
});

به همین سادگی فایل جدیدمون به route ها اضافه شد . یه روش دیگه هم هست برای اضافه کردن فایل admin.php که بدون تغییر فایل RouteServiceProvider.php انجام میشه ، به صورت زیر فایل جدید رو در web.php به این صورت require می‌کنیم :


Route::get('/', function () {
    return view('welcome');
});
 
Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth'])->name('dashboard');
 
require __DIR__.'/admin.php';

استفاده از Route::controller در لاراول 9

اگر شما متد های مختلفی دارید که همگی از یک controller استفاده می‎‌کنند به شکل زیر

Route::get('profile', [ProfileController::class, 'getProfile']);
Route::put('profile', [ProfileController::class, 'updateProfile']);
Route::delete('profile', [ProfileController::class, 'deleteProfile']);

می‌تونید به این صورت بازنویسی کنید :

Route::controller(ProfileController::class)->group(function() {
    Route::get('profile', 'getProfile');
    Route::put('profile', 'updateProfile');
    Route::delete('profile', 'deleteProfile');
});

این شکلی دیگه ProfileController::class رو کمتر تکرار میکنید و کدتون تمییز تر میشه البته این ویژگی در ورژن های آخر لاراول 8 هم قابل استفاده است !


کلاس های controller که نام مشترک دارند رو به چه صورت مدیریت کنیم؟

فرض کنید ما دو controller داریم : Admin/HomeController و User/HomeController اگر بخوایم از این موارد در route هامون استفاده کنیم این شکلی میشه :

Route::prefix('admin')->middleware('is_admin')->group(function () {
    Route::get('home', [\App\Http\Controllers\Admin\HomeController::class, 'index']);
});
 
Route::prefix('user')->middleware('is_user')->group(function () {
    Route::get('home', [\App\Http\Controllers\User\HomeController::class, 'index']);
});

که خب ظاهر زیاد جالبی نداره ! (نگید مهم نیست که ناراحت می‌شم)

اگر هم بخوایم از use استفاده کنیم و فقط نام controller رو در route استفاده کنیم نمیشه! چون هر دو یک اسم دارند یعنی این کد پایین قابلیت استفاده نداره

use App\Http\Controllers\Admin\HomeController;
use App\Http\Controllers\User\HomeController;

یه روش این هست که از as استفاده کنیم و برای یک مورد به اصطلاخ alias تعریف کنیم :

use App\Http\Controllers\Admin\HomeController as AdminHomeController;
use App\Http\Controllers\User\HomeController;
 
Route::prefix('admin')->middleware('is_admin')->group(function () {
    Route::get('home', [AdminHomeController::class, 'index']);
});
 
Route::prefix('user')->middleware('is_user')->group(function () {
    Route::get('home', [HomeController::class, 'index']);
})

که خب روش خوبیه و جواب میده ، یه روش دیگه هم این است که در route ها namespace تعریف کنیم :

Route::prefix('admin')->namespace('App\Http\Controllers\Admin')->middleware('is_admin')->group(function () {
    Route::get('home', [HomeController::class, 'index']);
    // ... other controllers from Admin namespace
});
 
Route::prefix('user')->namespace('App\Http\Controllers\User')->middleware('is_user')->group(function () {
    Route::get('home', [HomeController::class, 'index']);
    // ... other controllers from User namespace
});

اینم از این! خب دیگه الان یاد گرفتید به چه صورت route ها تمییز و کارامد بنویسید امیدوارم مفید بوده باشه مطلب و حتما دوس دارم نظرتون رو تو بخش کامنت ها بخونم و جواب بدم . و این مورد رو یادتون باشه تفاوت یک برنامه نویس junior با senior در همین موارد به ظاهر جزئی ولی مهم است . البته حقوقشون هم خیلی باهم فرق داره 😂

دیدگاه‌ها ۰