Pages

Wednesday, November 22, 2017

[1] LARAVEL Routing

Mình sẽ tóm lược tài liệu chính thức của Laravel, từ 23/11/2017

Basic Routing

Dưới đây là một ROUTE cơ bản, hàm Closure (hàm không có tên, có thể gán cho 1 biến $variable)cung cấp phương thức cơ bản định danh route này.
Route::get('foo', function () {
    return 'Hello World';
});

The Default Route Files

- Tất cả các route đều nằm trong thư mục routes.
- Tất cả đều được tự động triệu gọi (load). Có 4 tập tin trong thư mục: web, api, channel, console. Chúng ta chủ yếu làm việc với web.php.
- Có thể xây dựng một route để gọi hàm như sau: 
Route::get('/user', 'UsersController@index');
Với route trên, ta dùng phương thức GET, gọi tới /user trên trình duyệt, controller 'usercontroller" và phương thức @index được gọi.

Available Router Methods

Có 6 nhóm ROUTE cơn bản và phương thức đi kèm.
Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);
Đôi khi bạn cần đăng ký một route trả về một loạt tác vụ HTTP, bạn có thể dùng phương thứcmatc hoặc any:
Route::match(['get', 'post'], '/', function () {
    //
});

Route::any('foo', function () {
    //
});

CSRF Protection

Nếu dùng method POSTPUT, hay DELETE trong routes khi xử lý HTML cùng route web cần dùng một trường CSRF, nếu không request sẽ bị từ chối.
<form method="POST" action="/profile">
    {{ csrf_field() }}
    ...
</form>

Redirect Routes

Route này giúp chuyển tiếp sang URL, có hai tham số Route::redirect
Route::redirect('/here', '/there', 301);

View Routes (chỉ có từ 5.5)

Mới test thử trên bản 5.4 thì thấy lỗi, chưa có Route::viewnhư trên 5.5 Tương tự redirectphương thức này giúp bạn định nghĩa một route mà không cần phải bắt tay với controller, xả luôn dữ liệu ra view, gọi luôn view URL sẽ là tham số thứ nhất, view là tham số thứ hai. Ngoài ra, bạn có thể tạo array ở tham số thứ ba để truyền dữ liệu ra view, như ví dụ sau:
Route::view('/welcome', 'welcome');

Route::view('/welcome', 'welcome', ['name' => 'Taylor']);

Route Parameters

Required Parameters

Đôi khi bạn cần một segments của URL, chẳng hạn như ID để hiển thị, sửa hoặc xóa dữ liệu. Hãy xem xét ví dụ sau:
Route::get('user/{id}', function ($id) {
    return 'User '.$id;
});
Bạn có thể định nghĩa bao nhiêu tham số cũng được.
Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
    //
});
Các tham số của route sẽ nằm trong cặp ngoặc{} chứa số hoặc chữ, không chứa các dấu như -. Hãy dùng dấu gạch dưới thay vì gạch ngang (_). Tham số của route sẽ được chèn vào trong controller ở hàm callbacks theo đúng thứ tự của dấu / , tương ứng với hàm trong controller. Nghe loằng ngoằng nhưng tạm hiểu là với ví dụ trên, route là posts/{post}/comments/{comment} thì 2 tham số "cứng" (post và comment) hai tham số "mềm" (post/comment trong ngoặc{}). 

Optional Parameters

Đôi khi bạn chỉ cần một tham số ở dạng tùy chọn, hãy để dấu ? ở cuối tham số. Bạn cần đặt biến này với giá trị mặc định tương ứng, nếu như chúng không được gọi thì giá trị mặc định sẽ được gọi.
Route::get('user/{name?}', function ($name = null) {
    return $name;
});

Route::get('user/{name?}', function ($name = 'John') {
    return $name;
});

Regular Expression Constraints

Phương thức where sẽ giới hạn lại Route. Bạn có thể dùng REGEX với where. Xem xét các ví dụ sau:
Route::get('user/{name}', function ($name) {
    //
})->where('name', '[A-Za-z]+'); =================> name chỉ hiển thị chữ

Route::get('user/{id}', function ($id) {
    //
})->where('id', '[0-9]+'); ========================> id chỉ hiển thị số.

Route::get('user/{id}/{name}', function ($id, $name) {
    //
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

Global Constraints

Nếu bạn muốn tất cả các parameter đều bị khống chí bằng REGEX thì hãy sử dụng phương thức pattern.  Bạn có thể thiết lập trong phương thức boot trong RouteServiceProvider:
/**
 * Define your route model bindings, pattern filters, etc.
 *
 * @return void
 */
public function boot()
{
    Route::pattern('id', '[0-9]+'); =====================> tham số id đã được thiết lập REGEX là số

    parent::boot();
}
Một khi pattern đã được định nghĩa, hệ thống sẽ tự động áp dụng lên các tham số. 
Route::get('user/{id}', function ($id) {
    // Only executed if {id} is numeric...
});

Named Routes

Đây là cách ngọt canh để dùng với hàm route() sau này. Hãy dùng phương thức name 
Route::get('user/profile', function () {
    //
})->name('profile');
Bạn cũng có thể đặt tên route cho action của controller.
Route::get('user/profile', 'UserController@showProfile')->name('profile');

Generating URLs To Named Routes

Một khi bạn gán tên cho một route nào đó. Bạn có thể dùng tên của route khi tạo URL hoặc điều hướng (redirect) thông qua hàm route:
// Generating URLs...
$url = route('profile'); ============> tiện nhể :-)

// Generating Redirects...
return redirect()->route('profile');
Nếu cái route bạn đã gán tên định nghĩa một route, bạn có thể pass các parameter này với tư cách là argument thứ hai của hàm route. Các tham số đã cho sẽ tự động chèn vào URL theo vị trí chính xác.
Route::get('user/{id}/profile', function ($id) {
    //
})->name('profile');

$url = route('profile', ['id' => 1]);

Inspecting The Current Route

If you would like to determine if the current request was routed to a given named route, you may use the named method on a Route instance. For example, you may check the current route name from a route 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);
}

Route Groups

Route groups allow you to share route attributes, such as middleware or namespaces, across a large number of routes without needing to define those attributes on each individual route. Shared attributes are specified in an array format as the first parameter to the Route::group method.

Middleware

To assign middleware to all routes within a group, you may use the middleware method before defining the group. Middleware are executed in the order they are listed in the array:
Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {
        // Uses first & second Middleware
    });

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

Namespaces

Another common use-case for route groups is assigning the same PHP namespace to a group of controllers using the namespace method:
Route::namespace('Admin')->group(function () {
    // Controllers Within The "App\Http\Controllers\Admin" Namespace
});
Remember, by default, the RouteServiceProvider includes your route files within a namespace group, allowing you to register controller routes without specifying the full App\Http\Controllersnamespace prefix. So, you only need to specify the portion of the namespace that comes after the base App\Http\Controllers namespace.

Sub-Domain Routing

Route groups may also be used to handle sub-domain routing. Sub-domains may be assigned route parameters just like route URIs, allowing you to capture a portion of the sub-domain for usage in your route or controller. The sub-domain may be specified by calling the domain method before defining the group:
Route::domain('{account}.myapp.com')->group(function () {
    Route::get('user/{id}', function ($account, $id) {
        //
    });
});

Route Prefixes

The prefix method may be used to prefix each route in the group with a given URI. For example, you may want to prefix all route URIs within the group with admin:
Route::prefix('admin')->group(function () {
    Route::get('users', function () {
        // Matches The "/admin/users" URL
    });
});

Route Model Binding

When injecting a model ID to a route or controller action, you will often query to retrieve the model that corresponds to that ID. Laravel route model binding provides a convenient way to automatically inject the model instances directly into your routes. For example, instead of injecting a user's ID, you can inject the entire User model instance that matches the given ID.

Implicit Binding

Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name. For example:
Route::get('api/users/{user}', function (App\User $user) {
    return $user->email;
});
Since the $user variable is type-hinted as the App\User Eloquent model and the variable name matches the {user} URI segment, Laravel will automatically inject the model instance that has an ID matching the corresponding value from the request URI. If a matching model instance is not found in the database, a 404 HTTP response will automatically be generated.

Customizing The Key Name

If you would like model binding to use a database column other than id when retrieving a given model class, you may override the getRouteKeyName method on the Eloquent model:
/**
 * Get the route key for the model.
 *
 * @return string
 */
public function getRouteKeyName()
{
    return 'slug';
}

Explicit Binding

To register an explicit binding, use the router's model method to specify the class for a given parameter. You should define your explicit model bindings in the boot method of the RouteServiceProvider class:
public function boot()
{
    parent::boot();

    Route::model('user', App\User::class);
}
Next, define a route that contains a {user} parameter:
Route::get('profile/{user}', function (App\User $user) {
    //
});
Since we have bound all {user} parameters to the App\User model, a User instance will be injected into the route. So, for example, a request to profile/1 will inject the User instance from the database which has an ID of 1.
If a matching model instance is not found in the database, a 404 HTTP response will be automatically generated.

Customizing The Resolution Logic

If you wish to use your own resolution logic, you may use the Route::bind method. The Closure you pass to the bind method will receive the value of the URI segment and should return the instance of the class that should be injected into the route:
public function boot()
{
    parent::boot();

    Route::bind('user', function ($value) {
        return App\User::where('name', $value)->first() ?? abort(404);
    });
}

Form Method Spoofing

HTML forms do not support PUTPATCH or DELETE actions. So, when defining PUTPATCH or DELETE routes that are called from an HTML form, you will need to add a hidden _method field to the form. The value sent with the _method field will be used as the HTTP request method:
<form action="/foo/bar" method="POST">
    <input type="hidden" name="_method" value="PUT">
    <input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>
You may use the method_field helper to generate the _method input:
{{ method_field('PUT') }}

Accessing The Current Route

You may use the currentcurrentRouteName, and currentRouteAction methods on the Route facade to access information about the route handling the incoming request:
$route = Route::current();

$name = Route::currentRouteName();

$action = Route::currentRouteAction();
Refer to the API documentation for both the underlying class of the Route facade and Route instanceto review all accessible methods.
PS: Dùng từ điển Anh - Việt dùng để tra
https://laravel.com/docs/5.5/routing