algolia search

Tìm thấy x bài viết trong xms.

Chào các bạn, chắc hẳn mỗi khi bắt đầu tìm hiểu về Laravel thì các kiến thức cơ bản như Routing, Middleware, Controllers, Requests, Responses, Views là những khái niệm đầu tiên bạn cần phải biết để có thể sử dụng và làm quen với Laravel.

Trong bài viết này, mình sẽ đi sâu vào tìm hiểu về việc định tuyến trong Laravel. Đầu tiên, mục đích của Routing là để định tuyến các request của người dùng sẽ được đưa đến 1 Controller cụ thể nào đó để xử lý. Ở trong Laravel ta có thể hoàn toàn xử lý các dữ liệu đó trong phần Router.

Router được viết ở đâu?

Phiên bản Laravel 5.2 trở về trước router được viết vào file routes.php nằm ở app/Http/routes.php. Kể từ phiênbản Laravel 5.3 router được tách ra 1 thư mục riêng có tên là routes và đồng thời chia nhỏ (api, channels, console, web) các loại router để dễ quản lý. Bài viết này 

  • routes\web.php: định nghĩa các router trên trình duyệt web, sử dụng cookie, session, bảo vệ csrf,...
  • routes\api.php: định nghĩa các restful API
  • routes\channels.php: dùng cho việc broadcasting
  • routes\console.php: là nơi để bạn định nghĩa tất cả các Closure based console commands

1. Router cơ bản

Các router Laravel cơ bản nhất chấp nhận một URI và một Closure, cung cấp một phương thức xác định rất đơn giản và rõ ràng:

// http://chungnguyen.xyz/hello
Route::get('hello', function () {
    return 'Hello World';
});

Router Laravel có hỗ trợ các phương thức giống với http request method như GET, POST, PUT, PATCH, DELETE, OPTIONS, ...

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

Ngoài ra, laravel cũng hỗ trợ ta định nghĩa một route mà có thể xử lý nhiều loại method với chung một response bằng cách sử dụng phương thức matchany.

// Gửi http request get hoặc post đều trả về kết quả là match
Route::match(['get', 'post'], '/match', function () {
    return 'match';
});

// Gửi bất kỳ http request method nào cũng đều trả về kết quả là any
Route::any('any', function () {
    return 'any';
});

1.1 Bảo vệ CSRF

Tất cả các router được phủ bởi web middleware sẽ được bảo vệ CSRF với các method POST, PUT, DELETE. Khi bạn gửi request POST, PUT, DELETE lên server mà không kèm theo crsf token thì sẽ bị server từ chối vì lý do bảo mật, các bạn lưu ý nhé. Để chèn crsf token vào form các bạn làm như sau:

<form method="POST" action="/profile">
    @csrf
    ...
</form>

1.2 Chuyển hướng Routes

Mục đích là chuyển hướng routes, chẳng hạn bạn không dùng routes đó nữa hoặc chuyển sang địa chỉ mới..

Route::redirect('/dia-chi-cu', '/dia-chi-moi', $statusCode = 301);

1.3 View Routes

Nếu route của bạn chỉ đơn thuần muốn trả về 1 view mà không có xử lý logic gì hết thì đây là cách đơn giản hơn là phải trỏ về controller rồi controller lại trả về view.

Route::view('/welcome', 'welcome');
Route::view('/welcome', 'welcome', $datas = ['name' => 'Chung Nguyễn']);

2. Route có tham số

Route có tham số là tập hợp 1 số route có cùng logic xử lý, phù hợp cho tính linh động trong PHP.
Tham số route luôn luôn phải nằm trong dấu ngoặc nhọn {} và các tham số route không được phép chứa ký tự - nhé.

Route có tham số có 2 loại là:

  • Bắt buộc: {ten_tham_so} không truyền tham số khi gọi sẽ bị báo lỗi.
  • Không bắt buộc (thêm dấu ? sau tên của parameter): {ten_tham_so?} bạn hãy chắc chắn rằng đã khai báo giá trị mặc định
// ví dụ về Route không có tham số
Route::get('hello/chung', function() {
    return 'hello chung';
});
Route::get('hello/nguyen', function() {
    return 'hello nguyen';
});
Route::get('hello/blog', function() {
    return 'hello blog';
});

// Route có tham số bắt buộc
Route::get('hello/{name}', function($name) {
    return 'hello ' . $name;
});

// Route có tham số không bắt buộc
Route::get('hello/{name?}', function($name = 'Chung') {
    return 'hello ' . $name;
});

3.1 Ràng buộc biểu thức chính quy cho tham số

Rõ ràng với tham số truyền vào, chúng ta muốn giới hạn quy tắc cho tham số để ràng buộc bằng method where 

Route::get('user/{name}', function ($name) {
    // giới hạn tên là chữ cái hoa, thường.
})->where('name', '[A-Za-z]+');

Route::get('user/{id}', function ($id) {
    // giới hạn id chỉ được là số từ 0 - 9
})->where('id', '[0-9]+');

Route::get('user/{id}/{name}', function ($id, $name) {
    // ràng buộc cả id và name như đã giải thích ở trên
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

Ràng buộc biểu thức chính quy toàn cục (Global)

Giả sử bạn muốn hễ tham số là id thì phải là số từ 0-9 bạn không thể copy-paste mãi như vậy

Bạn nên định nghĩa ràng buộc trong hàm boot của app\Providers\RouteServiceProvider.php:

/**
 * Define your route model bindings, pattern filters, etc.
 *
 * @return void
 */
public function boot()
{
    Route::pattern('id', '[0-9]+');
    Route::pattern('name', '[A-Za-z]+');
    parent::boot();
}

4. Đặt tên cho các Route

Việc đặt tên cho các route rất có ý nghĩa và hữu dụng khi bạn muốn thay đổi URI mà không phải thay đổi quá nhiều code. Ví dụ: link đăng nhập trang web là https://chungnguyen.xyz/login và ở thời điểm nào đó mình thay đổi thành https://chungnguyen.xyz/dang-nhap như vậy mình sẽ phải đi lùng hết trong code chỗ nào có /login mình phải đổi thành /dang-nhap. Mình khuyên các bạn đặt name cho toàn bộ route, và gọi output route bằng name để quản lý chặt chẽ các liên kết trên website của mình.

Để đặt tên một route ta sử dụng phương thức name

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

Tạo URL từ route đã đặt tên

Một khi route đã được đặt tên, ta có thể sử dụng tên này qua phương thức route:

// Tạo URLs...
$url = route('profile');

// Tạo Redirects...
return redirect()->route('profile');

Nếu tên route được định nghĩa với tham số, bạn phải khai báo một đối số thứ hai trong phương thức route. Các đối số sẽ được chèn vào theo đúng thứ tự chính xác trên URLs:

Route::get('user/{id}/profile', function ($id) {
    //
})->name('profile');

// Tạo URL profile
$url = route('profile', $params = ['id' => 1]);

Kiểm tra route hiện tại

Một khi route đã được đặt tên bạn hoàn toàn có thể kiểm tra request đang gửi tới có thuộc name nào? và code logic theo yêu cầu

Ví dụ: bạn có thể kiểm tra name route hiện tại từ middleware:

/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 */
public function handle($request, Closure $next)
{
    if ($request->route()->named('profile')) {
        //
    }

    return $next($request);
}

5. Nhóm route

Khi các route có chung tiền tố, chung middle, chung namespace, ... thì các bạn nên gom chúng lại với nhau mà không cần định nghĩa lại chúng trên mỗi route riêng. 

Ví dụ chung middleware

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

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

Ví dụ chung namespace

Route::namespace('User')->group(function () {
    // controller sẽ sử dụng App\Http\Controllers\User làm namespace
});

Ví dụ chung tiền tố:

Route::prefix('admin')->group(function () {
    Route::get('users', function () {
        // https://chungnguyen.xyz/admin/users
    });
    Route::get('settings', function () {
        // https://chungnguyen.xyz/admin/settings
    });
});

Ví dụ chung tiền tố name route

Route::name('admin.')->prefix('admin')->group(function () {
    Route::get('users', function () {
        // Tạo url: $url = route('admin.users')
    })->name('users');
    Route::get('settings', function () {
        // Tạo url: $url = route('admin.settings')
    })->name('settings');
});

6. Truy cập route hiện tại

Bạn có thể sử dụng phương thức current, currentRouteName, và currentRouteAction trên Route facade để truy cập thông tin về resquest route xử lý đang đến:

$route = Route::current();

$name = Route::currentRouteName();

$action = Route::currentRouteAction();

Đánh giá bài viết

Thích thì like
Laravel Routing - Toàn tập về định tuyến trong Laravel
5/5 1 votes

Bình luận

Hiển thị bình luận Facebook