چگونگی مدیریت Routeها در پروژه‌های بزرگ در لاراول

گردآوری و تالیف : رضا جمال زاده
تاریخ انتشار : 18 مهر 1398
دسته بندی ها : لاراول

تصور کنید پروژه لاراولی با بیش از 100 روت دارید، که این پروژه دارای بخش‌های جداگانه‌ای برای مهمان‌ها، کاربران، مدیران و... است، آیا شما واقعاً می‌خواهید همه این قسمت‌ها را در یک فایل نگهداری کنید؟ در این مقاله به بررسی روش‌های مختلف دسته‌بندی و مدیریت روت‌ها می‌پردازیم.

1-جدا کردن روت‌های web وapi 

 این مورد ساده است زیرا لاراول به صورت پیش‌فرض دو فایل زیر را برای روت‌های web وapi  قرار داده است.

  

بنابراین اگر پروژه شما دارای هر دو صفحه web وapi  است (این روش اخیراً خیلی متداول شده است) لطفاً روت‌های api را در یک فایل جداگانه قرار دهید. برای مثال اگر شما صفحه /users و همچنین صفحه  /api/users/آن را دارید قرار دادن این روت‌ها در فایل‌های جداگانه از آشفتگی و اشتباه گرفتن این دو با هم جلوگیری می‌کند.

2-قرار دادن web روت‌ها در گروه‌های مشخص

 این روش جزء روش‌های اساسی گروه‌بندی روت‌ها در لاراول است، به مثال زیر توجه کنید:

Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {
        // Uses first & second Middleware
    });

    Route::get('user/profile', function () {
        // Uses first & second Middleware
    });
});

بیش‌ترین استفاده از این روش برای قرار دادن گروه‌های مختلف در زیر middlewareهای مختلف است، برای مثال شما یک گروه روت دارید می‌خواهی به صورت پیش‌فرض توسط middleware:auth محدود شده باشند و همچنین گروه دیگر توسط middleware شخصی‌سازی شده‌ای به نام admin محدود شده باشند و... . همچنین با این روش شما می‌توانید از پسوندها و نام‌ها (prefix و name) برای گروه‌ها استفاده کنید. به مثال‌های زیر توجه کنید:

Route::prefix('admin')->group(function () {
    Route::get('users', function () {
        // Matches The "/admin/users" URL
    });
});

Route::name('admin.')->group(function () {
    Route::get('users', function () {
        // Route assigned name "admin.users"...
    })->name('users');
});

 همچنین اگر شما می‌خواهید همه پسوند و نام و middleware را بر روی یک گروه اضافه کنید، قرار دادن این موارد در یک آرایه باعث خوانایی بیش‌تر آن‌ها می‌شود:

// Instead of chaining like this: 
Route::name('admin.')->prefix('admin')->middleware('admin')->group(function () {
    // ...
});

// You can use an array
Route::group([
    'name' => 'admin.', 
    'prefix' => 'admin', 
    'middleware' => 'auth'
], function () {
    // ...
});

 در ادامه بیاید همه موارد بالا را در یک مثال عینی‌تر در سه گروه جداگانه قرار دهیم:

1-گروه مهمان(Gaest) با URL،  /front/XXXXX و بدون middleware

2-گروه کاربر(user) با URL،  /user/XXXXX و با middleware، auth

3- گروه ادمین(admin) با URL،  /admin/XXXXX و با middleware شخصی‌سازی شده، admin

در زیر مثالی برای گروه‌بندی روت‌ها با استفاده از این روش در فایل routes/web.php آورده شده است:

Route::group([
    'name' => 'admin.',
    'prefix' => 'admin',
    'middleware' => 'admin'
], function () {

    // URL: /admin/users
    // Route name: admin.users
    Route::get('users', function () {
        return 'Admin: user list';
    })->name('users');

});

Route::group([
    'name' => 'user.',
    'prefix' => 'user',
    'middleware' => 'auth'
], function () {

    // URL: /user/profile
    // Route name: user.profile
    Route::get('profile', function () {
        return 'User profile';
    })->name('profile');

});

Route::group([
    'name' => 'front.',
    'prefix' => 'front'
], function () {

    // No middleware here
    // URL: /front/about-us
    // Route name: front.about
    Route::get('about-us', function () {
        return 'About us page';
    })->name('about');

});

3-گروه‌بندی کنترلرها با Namespaces

در مثال‌های بالا ما از کنترلرها در روت‌های خود استفاده نکردیم و فقط یک متن را به صورت استاتیک بازگرداندیم. بیاید کنترلرها را با یک چینش دیگر قرار دهیم. ما می‌خواهیم آن‌ها را در پوشه‌هایی با namespaces متفاوت خودشان قرار دهید مانند زیر:

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

Route::group([
    'name' => 'front.',
    'prefix' => 'front'
], function () {
    Route::get('about-us', 'Front\AboutController@index')->name('about');
});

 اما اگر ما کنترلرهای زیادی داشته باشیم چه کاری باید انجام دهیم؟ آیا باید همیشه Front\SomeController را اضافه کنیم؟ البته که نه، شما به سادگی می‌توانید namespaces  مورد نظر خود را به عنوان یک پارامتر در روت مورد نظر خود قرار دهید.

Route::group([
    'name' => 'front.',
    'prefix' => 'front',
    'namespace' => 'Front',
], function () {
    Route::get('about-us', 'AboutController@index')->name('about');
    Route::get('contact', 'ContactController@index')->name('contact');
});

 4-گروه‌بندی تو در تو

 وضعیت بالا به وسیله سه گروه به سادگی مدیریت شده است، اما در پروژه‌های واقعی شرایط کمی متفاوت است. در این پروژه‌ها دو گروه: front و auth وجود دارد و همچنین در گروه auth  زیرگروه‌های کاربر و ادمین وجود دارد. برای مدیریت کردن آن‌ها ما می‌توانیم در فایل روت خود زیر گروه‌هایی ایجاد کنیم و middleware و پیشوندهای مختلفی را به آن‌ها اختصاص دهیم:

Route::group([
    'middleware' => 'auth',
], function() {

    Route::group([
        'name' => 'admin.',
        'prefix' => 'admin',
        'middleware' => 'admin'
    ], function () {

        // URL: /admin/users
        // Route name: admin.users
        Route::get('users', 'UserController@index')->name('users');

    });

    Route::group([
        'name' => 'user.',
        'prefix' => 'user',
    ], function () {

        // URL: /user/profile
        // Route name: user.profile
        Route::get('profile', 'ProfileController@index')->name('profile');

    });

});

Route::group(['middleware' => 'language'], function () {
    Route::group(['middleware' => 'auth'], function () {
        Route::group(['prefix' => 'uploads'], function () {
            Route::get('{id}', 'Common\Uploads@get');
            Route::get('{id}/show', 'Common\Uploads@show');
            Route::get('{id}/download', 'Common\Uploads@download');
        });

        Route::group(['middleware' => 'permission:read-admin-panel'], function () {
            Route::group(['prefix' => 'wizard'], function () {
                Route::get('/', 'Wizard\Companies@edit')->name('wizard.index');
        
        // ...

همچنین ما می‌توانیم این کار را با بیش از دو سطح انجام دهیم. به مثال‌های زیر توجه کنید:

Route::middleware(['auth', 'verified', 'mfa'])->group(function () {
    Route::name('dashboard.')->group(function () {
        Route::get('/dashboard', 'DashboardController@index')->name('index');
        Route::get('/dashboard/calls', 'DashboardController@calls');
        Route::get('/dashboard/notes', 'DashboardController@notes');
        Route::get('/dashboard/debts', 'DashboardController@debts');
        Route::get('/dashboard/tasks', 'DashboardController@tasks');
        Route::post('/dashboard/setTab', 'DashboardController@setTab');
    });

 5-تنظیمات عمومی در RouteServiceProvider لاراول

در لاراول فایل app/Providers/RouteServiceProvider.php که برای تنظیم همه روت‌ها استفاده می‌شود، وجود دارد. در این فایل متد map() وجود دارد که هر دو فایل روت web و api را به هم مرتبط می‌کند:

public function map()
    {
        $this->mapApiRoutes();
        $this->mapWebRoutes();
    }

    protected function mapWebRoutes()
    {
        Route::middleware('web')
             ->namespace($this->namespace)
             ->group(base_path('routes/web.php'));
    }

    protected function mapApiRoutes()
    {
        Route::prefix('api')
             ->middleware('api')
             ->namespace($this->namespace)
             ->group(base_path('routes/api.php'));
    }

آیا تا این‌جا متوجه شدید که middleware،namespace  و پیشوندها در این متد آورده شده‌اند؟ در واقع این متد جایی است که شما می‌توانید تنظیمات مختلفی برای همه روت‌های خود اعمال کنید، بنابراین با این کار شما نیاز ندارید که تنظیمات مورد نظر خود را بر روی تک تک گروه‌های روت خود در فایل روت تکرار کنید.

 این روش بیش‌تر برای روت‌های api استفاده می‌شود، زیرا تنظیمات آن‌ها معمولاً یکسان هستند مانند زیر:

protected function mapApiRoutes()
{
    Route::group([
        'middleware' => ['api'],
        'namespace' => $this->namespace,
        'prefix' => 'api/v1',
    ], function ($router) {
        require base_path('routes/api.php');
    });
}

 با استفاده از متد بالا برای همه‌ی URLهای api پیشوند api/v1/ ، قرار داده شده است.

6-گروه‌بندی در فایل‌های بیشتر-آیا این کار ارزش دارد؟

 اگر تعداد زیادی روت در پروژه خود دارید و همچنان می‌خواهید بر تعداد آن‌ها اضافه کنید، همچنین می‌خواهید که از فایل های جداگانه برای گروه‌بندی آن‌ها استفاده کنید، پس شما می‌توانید از فایل ذکر شده در بخش قبل - app/Providers/RouteServiceProvider.php - استفاده کنید. اگر شما نگاهی به متد map() در این فایل بیندازید در انتهای آن کامنت‌هایی برای ارائه موارد جدید می‌بینید:

public function map()
{
    $this->mapApiRoutes();

    $this->mapWebRoutes();

    //
}

 شما می‌توانید این کامنت را مانند یک دعوت برای قرار دادن فایل‌های بیشتر در این متد در نظر بگیرید، اگر تمایل به قرار دادن فایل دیگری دارید، شما می‌توانید موارد دیگری مانند mapAdminRoutes() در متد map() این فایل ایجاد کنید. پس از آن این متد به طور خودکار فایل شما را ثبت کرده و لود می‌کند.

اما شخصاً، من مزیت زیادی در این رویکرد ندیده‌ام و خیلی کم دیده‌ام که این کار را انجام دهند. قرار دادن روت‌ها در فایل‌های جداگانه فاصله بیشتری بین آن‌ها قرار می‌دهد و مزیت کوچکی نیز به حساب می‌آید، اما گاهی اوقات این کار ممکن است باعث شود که شما در این فایل‌ها سردرگم شوید و مطمئن نباشید که کجا باید روت مورد نظر خود را پیدا کنید.

7-فهمیدن اطلاعات دقیق روت‌ها با دستور Artisan route:list

 وقتی صحبت از تعداد خیلی زیادی از روت‌ها می‌شود احتمال گم شدن در آن‌ها هم بالا می‌رود. برای حل این مشکل و پیدا کردن یک روت خاص از بین انبوهی از روت‌ها، ما می‌توانیم از دستور php artisan route:list استفاده کنیم.

 احتمالاً همه شما می‌دانید که دستور بالا همه روت‌های موجود در پروژه را نشان می‌دهد:

 اما آیا شما از قابلیت فیلتر کردن روت‌ها برای راحت‌تر پیدا کردن روت مورد نظر خود اطلاعی دارید؟ برای این کار تنها کافی است موارد –method یا  –nameو یا –path را به عنوان پارامتر قرار دهیم.

فیلتر کردن بر اساس متد  GET, POST

فیلتر با نام و یا قسمتی از URL

روش‌های بالا، روش‌هایی هستند که برای گروه‌بندی روت‌ها در پروژه‌های بزرگ با روت‌های خیلی زیاد مورد استفاده قرار می‌گیرند. اگر شما روش دیگری برای این کار می‌شناسید، لطفاً در قسمت نظرات آن را با ما به اشتراک بگذارید.

منبع

مقالات پیشنهادی

  • ساخت و مدیریت قالب ها در لاراول

    در این مقاله می خواهیم یک پکیج جالب و کاربردی لاراول به اسم laravel-theme رو بررسی کنیم. این یک پکیج پایه است که مدیریت قالب ها (تم ها) در لاراول رو پ...

    امیررضا سیستانه ای
  • برنامه‌‌های لاراول در مقیاس بزرگ

    همه می‌دانیم که لاراول، معروف‌ترین فریمورک php است. ساختار پوشه بندی لاراول بسیار مطلوب، ساده و برای درک کردن واضح است. وقتی ما با پروژه‌های متوسط و ک...

    عارف دیلمی
  • مدیریت رویدادها در لاراول

    رویداد (Event) یک عمل یا اتفاقی هست که توسط برنامه سازماندهی شده که ممکنه توسط برنامه هم مدیریت بشه. رویدادهای لاراول بسادگی پیاده سازی می شوند. رویدا...

    امیررضا سیستانه ای
  • ساخت و مدیریت خبرنامه ها در لاراول 5

    در این آموزش شما میتونید نحوه ی افزودن لیست خبرنامه, مدیریت اعضا و فرستادن ایمیل به لیست ها رو با استفاده از Api سرویس Mailchimp در فریمورک لاراول 5 ف...

    امیررضا سیستانه ای