ساختار بندی روت های خود را در پروژه های بزرگ لاراولی چگونه انجام دهیم؟

ساختار بندی روت های خود را در پروژه های بزرگ لاراولی چگونه انجام دهیم؟
28 دی 1399, خواندن در 6 دقیقه

در این مطلب به نحوه‌ی ساختار بندی روت ها در پروژه های بزرگ لاراولی خواهیم پرداخت. تصور کنید که یک پروژه لاراولی با +۱۰۰ Route دارید، بخش‌های جداگانه برای guest،users و administrators و موارد دیگر را نیز داراست. خب آیا واقعاً می‌خواهید همه‌ی این‌ها را در یک فایل نگهداری کنید؟چگونه می‌توانیم آن‌ها را گروه بندی کنیم یا چه پرفیکس‌هایی باید به URL های خود اضافه کنیم؟ خب بیایید ببینیم اصلاً چه گزینه‌هایی داریم؟

۱.روت های WEB و API را جدا کنید

این یکی راحته چون لاراول به طور پیش‌فرض این فیچر را داراست. در‌واقع دوفایل وجود دارد:

  • routes/web.php
  • routes/api.php

بنابراین اگر پروژه شما هم دارای هر دو،‌ یعنی صفحه‌های بصری و API است( که امروزه بسیار رایج‌تر است) لطفاً روت های API را در آن فایل جداگانه قرار دهید.

به عنوان مثال، اگر شما صفحه‌ی /users و سپس /api/users/ را داشته باشید، جدا کردن آن‌ها و قرار دادنشان در فایل‌های خودشان باعث می‌شود تا با فایل‌های همنام موجود در همان فایل اشتباه گرفته نشوند.

با تمام این اوصاف، من اخیراً نمونه‌ای ضد از پروژه رسمی لاراول دیدم. با لاراول Horizon، تیلور فقط روت های API را دارد و دیگر از فایلی جداگانه استفاده نکرده و در عوض آن را در routes/web.php قرار داده :

ساختار بندی روت های خود را در پروژه های بزرگ لاراولی چگونه انجام دهیم؟

و دلیلش این است که ساختار در لاراول بسیار شخصی است و هیچ استاندارد ۱۰۰ درصدی، حتی از طرف خود تیلور نیز وجود ندارد.

۲. ساختار فایل routes/web.php را گروهی کنید

این امر نیز از مواردی است که از پایه در لاراول وجود دارد- منظورم گروه‌بندی روت‌هاست. این یک مثال از داکیومنت رسمی لاراول است:

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

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

اساسی‌ترین کاربرد آن پنهان کردن گروه‌های مختلف زیر middleware های مختلف است. به عنوان مثال، شما گروهی می‌خواهید که با auth middleware پیش‌فرض محدود شده باشد و گروه دیگر باadmin custom middleware جدا شده باشد و موارد دیگر.

با این خواسته‌ها، شما می‌توانید از نام‌ها و prefixe های Route group نیز استفاده کنید. بازهم چند نمونه از داکیومنت اصلی :

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+name+prefix را به یک گروه اضافه کنید، می‌توانید آن‌ها را در یک آرایه قرار دهید تا خواناتر باشد.

// 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 () {
    // ...
});

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

  • گروه “Guest” با URLهای  /front/XXXXX و بدون middleware ؛
  • گروه “User” با URLهای /user/XXXXX و auth middleware ؛
  • گروه “Admin” با URLهای /admin/XXXXX  و admin middleware دلخواه.

در این‌جا روشی به شما نشان خواهم داد تا همه‌ی این‌ها را در فایل 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');

});

۳. گروه‌بندی Controllerها با Namespace ها

در مثال بالا، ما از Controller ها استفاده نکردیم، و فقط یک متن استاتیک را به عنوان نمونه return کردیم. بیایید Controller ها را با پیچ و تاب بیشتری اضافه کنیم – ما آ‌ن‌ها را در پوشه‌هایی با namespaceهای مختلف خودشان ساختاربندی می‌کنیم. مثل این :

ساختار بندی روت های خود را در پروژه های بزرگ لاراولی چگونه انجام دهیم؟

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

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

اما اگر ما controller های زیادی در آن‌ گروه داشته باشیم چه؟ آیا باید به صورت تمام وقت Front\SomeControlle اضافه کنیم؟ البته که نه. شما می‌توانید namespace را به عنوان یکی از پارمتر‌ها مشخص کنید.

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

۴. گروه بندی داخل یک گروه

موقعیت بالا، با سه گروه، ساده شده است؛ اما پروژه‌های واقعی ساختاری متفاوت‌تر دارند. از دو گروه :front و auth ساخته شده‌اند. و سپس داخل auth زیر گروه وجود دارد. برای این منظور می‌توانید زیرگروه‌هایی در routes/web.php ایجاد کنید و به middlewares/prefixes مختلف اختصاص دهید.

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

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

        // URL: /admin/users
        // Route name: admin.users
        Route::get('users', '[email protected]')->name('users');

    });

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

        // URL: /user/profile
        // Route name: user.profile
        Route::get('profile', '[email protected]')->name('profile');

    });

});

همینطور می‌توانیم این کار را حتی با بیش از دو سطح نیز انجام دهیم، در اینجا مثالی از پروژه اپن سورس Akaunting آورده شده است :

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

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

و همچنین مثالی دیگر از CRM محبوب لاراول به نام Monica :

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

۵. تنظیمات Global در RouteServiceProvider

فایلی وجود دارد که برای تنظمیات همه‌ی روت‌ها سرو می‌شود – app/Providers/RouteServiceProvider.php ؛ و دارای متد map() است که در آن دو فایل رو‌ت‌های ما را bind می‌کند.( به عبارتی بهم گره می‌زند ) - 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 و prefix در این متدها استفاده می‌شود؟ اینجاست که می‌توانید تنظیمات global را برای تمام فایل‌ها ست کنید، پس دیگر نیاز نیست که آن‌ها را برای هر Route group داخل این فایل تکرار کنید.

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

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

متد بالا  برای تمام API URL ها پریفیکس api/v1/ را قرار می‌دهد.

۶.گروه‌بندی در فایل‌های بیشتر – آیا واقعاً ارزش دارد؟

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

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

    $this->mapWebRoutes();

    //
}

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

اما من شخصاً مزیت زیادی در این روش نمیبینم، و ندیده‌ام که از این روش زیاد استفاده کنند. این کار تفکیک روت‌ها را بیشتر می‌کند، اما گاهی در این فایل گم می‌شوید و مطمئن نیستید که کجا باید دنبال آن روت بگردید.

۷. روت دقیق را با Artisan route پیدا کنید :list command

صحبت از روت های بزرگ‌تر و گم شدن میان آن‌ها شد، ما یک دستور Artisan داریم که به مکان‌یابی دقیق یک روت خاص کمک می کند.

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

ساختار بندی روت های خود را در پروژه های بزرگ لاراولی چگونه انجام دهیم؟

اما آیا می‌دانید که می‌توانید برای یافتن مورد دقیق‌تر فیلتر بیشتری انجام دهید؟ فقط –method یا –name یا –path را با پارامترهای آن اضافه کنید.

method – GET یا POST یا موارد دیگر فیلتر شود :

ساختار بندی روت های خود را در پروژه های بزرگ لاراولی چگونه انجام دهیم؟

با نام یا قسمت URL فیلتر شود :

ساختار بندی روت های خود را در پروژه های بزرگ لاراولی چگونه انجام دهیم؟

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

منبع

چه امتیازی به این مقاله می دید؟
خیلی بد
بد
متوسط
خوب
عالی

دیدگاه‌ها و پرسش‌ها

برای ارسال دیدگاه لازم است، ابتدا وارد سایت شوید.

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

آفلاین
user-avatar
فاطمه شیرزادفر @Fatemeh.shirzadfar
تجربه کلمه‌ای هست که همه برای توصیف اشتباهاتشون ازش استفاده میکنن، و من همیشه دنبال اشتباهات جدیدم! برنامه‌نویس هستم و لینوکس‌ دوست
دنبال کردن

گفتگو‌ برنامه نویسان

بخشی برای حل مشکلات برنامه‌نویسی و مباحث پیرامون آن وارد شو