Laravel: Làm thế nào để cấu trúc routes các dự án Thương mại điện tử?

01.09.2020

5.0/5 (1 Reviews)

Laravel: Làm thế nào để cấu trúc routes các dự án Thương mại điện tử?

    Hãy tưởng tượng một dự án Laravel với hơn 100+ routes, chia ra các phần riêng biệt dành cho khách, người dùng, quản trị viên, .... Bạn có thực sự muốn giữ tất cả trong một file không? Làm thế nào bạn có thể nhóm chúng, thêm tiền tố vào các URL? Hãy cùng xem những cách chúng ta có.

    Separate WEB and API Routes

    Việc này là dễ dàng, vì trong default của Laravel chúng ta có 2 files:

    Vì vậy, nếu dự án của bạn có cả trang web-pages và API (ngày càng phổ biến hơn), vui lòng đặt các API routes trong file riêng biệt đó.

    Ví dụ: nếu bạn có /users page và sau đó /api/users/ endpoint, việc tách chúng ra các file riêng giúp chúng ta không bị nhầm lẫn giữa cùng name trong cùng file.

    Điều đó có nghĩa rằng, gần đây tôi đã thấy ví dụ phản trực quan từ offical Laravel project. Với Laravel Horizon, Taylor chỉ có các API routes và anh ấy đã không sử dụng file riêng biệt, thay vào đó anh ấy đưa nó vào routes/web.php:

    Một bằng chứng khác cho thấy cấu trúc trong Laravel rất cá nhân và không có tiêu chuẩn nào là 100%, ngay cả từ chính Taylor.

    Structure routes/web.php File into Groups

    Điều đó cũng xuất phát từ "basic" Laravel - route. Đây là một ví dụ từ :

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

    Cách sử dụng cơ bản nhất là ẩn các groups khác nhau dưới các middleware khác nhau. Ví dụ: bạn muốn một group bị hạn chế bởi middleware auth mặc định, một group khác bằng custom middlware admin, ...

    Cùng với đó, bạn cũng có thể sử dụng Route group nameprefix. Một vài ví dụ khác từ offical documentation:

    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');
    });
    

    Tương tự, nếu bạn muốn thêm tất cả các middleware+name+prefix vào 1 group, nó sẽ dễ đọc hơn nếu bạn nhét chúng vào một array:

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

    Hãy liên kết tất cả lại với nhau thành một ví dụ thực tế với 3 groups:

    • “Guest” group with /front/XXXXX URLs and no middleware;
    • “User” group with /user/XXXXX URLs and auth middleware;
    • “Admin” group with /admin/XXXXX URLs and custom admin middleware.

    Đây là cách để nhóm chúng vào trong routes/web.php file:

    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');
    
    });
    

    Grouping Controllers with Namespaces 

    Trong ví dụ trên, chúng ta đã không sử dụng Controllers, chúng ta chỉ trả lại static text như một ví dụ. Hãy thêm Controller, với thêm một "twist" - chúng ta sẽ cấu trúc chúng vào các thư mục với các namespaces khác nhau của chúng, như thế này:

    Và sau đó chúng ta có thể sử dụng chúng trong Routes file:

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

    Nhưng nếu chúng ta có nhiều Controllers trong group đó thì sao? Chúng ta có nên tiếp tục thêm Front\SomeController mọi lúc không? Tất nhiên là không. Bạn cũng có thể chỉ định namespace là một trong các tham số.

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

    Group within a Group

    Tình huống trên, với ba groups, được đơn giản hóa, các dự án thực tế có cấu trúc hơi khác nhau - gồm hai group: frontauth. Và sau đó bên trong auth có các sub-group: useradmin. Vì vậy, chúng ta có thể tạo các sub-group trong routes/web.php và gán các middleware/prefix khác nhau, ...

    Route::group([
        'middleware' => 'auth',
    ], function() {
    
        Route::group([
            'name' => 'admin.',
            'prefix' => 'admin',
            'middleware' => 'admin'
        ], function () {
    
            // URL: /admin/users
            // Route name: admin.users
            Route::get('users', '')->name('users');
    
        });
    
        Route::group([
            'name' => 'user.',
            'prefix' => 'user',
        ], function () {
    
            // URL: /user/profile
            // Route name: user.profile
            Route::get('profile', '')->name('profile');
    
        });
    
    });
    

    Chúng ta có thể làm điều đó ngay cả với hơn hai cấp độ, đây là một ví dụ từ dự án open source :

    Route::group(['middleware' => 'language'], function () {
        Route::group(['middleware' => 'auth'], function () {
            Route::group(['prefix' => 'uploads'], function () {
                Route::get('{id}', 'Common\');
                Route::get('{id}/show', 'Common\');
                Route::get('{id}/download', 'Common\');
            });
    
            Route::group(['middleware' => 'permission:read-admin-panel'], function () {
                Route::group(['prefix' => 'wizard'], function () {
                    Route::get('/', 'Wizard\')->name('wizard.index');
            
            // ...
    

    Một ví dụ khác từ Laravel CRM phổ biến khác :

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

    Global Settings in RouteServiceProvider

    Có 1 file phục vụ cho tất cả các routes setting - app/Providers/RouteServiceProvider.php. Nó có method map() nơi mà bind cả 2 files routes - webapi.

        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'));
        }
    

    Bạn có nhận thấy middleware, namespaceprefix được đề cập trong các method không? Đó là nơi bạn có thể thiết lập các setting chung cho toàn bộ file, do đó, bạn sẽ phải lặp lại chúng cho mỗi Route group trong file.

    Nó chủ yếu được sử dụng cho các API routes, vì các cài đặt của chúng thường giống nhau, như sau:

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

    Method này sẽ prefix tất cả API URLs vơi api/v1/ khi bắt đầu.

    Grouping into More Files – is it worth it?

    Nếu bạn có số lượng routes lớn và muốn group chúng nhiều hơn, vào các file riêng biệt, thì bạn có thể sử dụng cùng một file được đề cập trong phần trước - app/Providers/RouteServiceProvider.php. Nếu bạn xem xét kỹ hơn các phương thức map() của nó, bạn sẽ thấy commented out ở cuối:

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

    Bạn có thể diễn giải nó như một "invitation" để thêm nhiều files hơn, nếu bạn muốn. Vì vậy, bạn có thể tạo một phương thức khác như mapAdminRoutes() bên trong file này, sau đó thêm nó vào phương thức map() và file riêng biệt của bạn sẽ được đăng ký và load tự động.

    Nhưng, cá nhân tôi, tôi không thấy nhiều lợi ích trong cách tiếp cận này và tôi không thấy nó được thực hiện thường xuyên. Nó mang lại một chút riêng biệt trong routes, nhưng đôi khi bạn bị lạc trong các file đó và không chắc chắn nơi để tìm thấy các route cụ thể.

    Find Exact Route with Artisan route:list command

    Nói về các routes lớn hơn và bị lạc ở đó, chúng ta có một aritsan command giúp xác định vị trí một route nhất định.

    Có lẽ tất cả các bạn đều biết rằng php artisan route:list sẽ cung cấp cho bạn tất cả các routes trong dự án:

    Nhưng bạn đã biết cách filter để tìm chính xác điều bạn muốn? Hãy thêm parameters -method, hoặc -name hoặc -path:

    Filter by method - GET, POST:

    Filter by name hoặc URL part:

    Chúc các bạn học tốt

    CÓ THỂ BẠN QUAN TÂM

    Bài Viết Cùng Chuyên Mục

    XEM THÊM
    thumbnail

    LPStack Server: Giải pháp thay thế XAMPP và MAMP năm 2026

    10.03.2026

    Bạn đã chán ngấy XAMPP hay MAMP chậm chạp? Khám phá LPStack Server – Môi trường Local Development siêu nhẹ của người Việt với Auto Vhost, Public Tunnel, chuyển đổi PHP 1-click và quản lý Database Native chuyên nghiệp

    thumbnail

    Hướng Dẫn Tạo Trò Chơi Cờ Caro Nâng Cao bằng HTML

    19.03.2025

    Chào các bạn! Trong bài viết này, chúng ta sẽ cùng nhau xây dựng một trò chơi Cờ Caro đơn giản nhưng có nhiều tính năng thú vị như giới hạn nước đi, pháo hoa khi chiến thắng, chọn chế độ chơi và đếm thời gian.

    thumbnail

    Grok AI: Giới thiệu chi tiết về chatbot của Elon Musk

    04.03.2025

    Grok là một chatbot AI tiên tiến, được phát triển bởi xAI, công ty do Elon Musk sáng lập. Ra mắt lần đầu vào tháng 11/2023, Grok được thiết kế để cạnh tranh với các mô hình AI nổi tiếng như ChatGPT

    thumbnail

    Hướng dẫn tạo Livechat trả lời bằng AI Grok của X

    04.03.2025

    Hướng dẫn kỹ thuật tạo Livechat AI bằng HTML, CSS, JavaScript và PHP Dưới đây là hướng dẫn từng bước để xây dựng một ứng dụng livechat AI đơn giản. Chúng ta sẽ có giao diện frontend (HTML, CSS, JS) và backend (PHP) xử lý tin nhắn.

    thumbnail

    Temu Affiliate là gì? Cách kiếm tiền với Temu mới nhất 2024

    23.10.2024

    Temu Affiliate là một chương trình tiếp thị liên kết mới mẻ được đưa ra bởi sàn thương mại điện tử Temu. Tham gia ⭐️ Chương trình tiếp thị liên kết Temu⭐️! Lên đến ????₫2.500.000.000 mỗi tháng