LỜI NÓI ĐẦU Trong những năm gần đây, công nghệ thông tin đã dần khẳng định được vai trò quan trọng và là một phần tất yếu trong sự nghiệp phát triển kinh tế - xã hội của đất nước. Đối với doanh nghiệp, công nghệ thông tin là một yếu tố góp phần quan trọng trong việc đổi mới phương thức quản lý, sản xuất cũng như kinh doanh. Với đó ngành công nghệ thông tin cũng phát triển theo trong đó, có rất nhiều ngôn ngữ lập trình ngôn ngữ lập trình mới hỗ trợ việc xây dựng các ứng dựng web điển hình là Laravel. Laravel là 1 framework PHP được phát triển bởi Taylor Otwell vào năm 2011. Là 1 mã nguồn mở và hoàn toàn miễn phí, laravel được sinh ra nhằm mục đích hỗ trợ các ứng dụng web sử dụng mô hình MVC (Model, Controller, View). Laravel như một giải pháp thay thế cho CodeIgniter, cung cấp nhiều tính năng vượt trội như composer, xác thực, phân quyền... Vì là 1 framework khá mới nên Laravel thừa hưởng ưu điểm và thế mạnh từ những framework đi trước như CodeIgniter, Yii, .....và dần trở thành thay thế cho các framework cũ kỹ như Cake hay Yii, ASP.NET MVC, Ruby on Rails… Trong đó Laravel tích hợp composer làm công cụ quản lý, sử dụng blade template giúp việc quản lý template thật đơn giản, việc thao tác với Cơ Sở Dữ Liệu thật dễ dàng với Query Buider hoặc ORM. Website đa ngôn ngữ luôn là điều được các lập trình viên quan tâm khi sử dụng framework, trong Laravel mọi chuyện trở nên dễ dàng hơn. Laravel cung cấp cho người dùng một cách thức đơn giản để ứng dụng đa ngôn ngữ. Hà Nội, ngày 21 tháng 2 năm 2018 Tác giả
MUC LUC CHƯƠNG 1. 1.1.
ROUTING 1
Cơ bản về Routing 1
1.1.1.
File ruote mặc định 1
1.1.2.
Các phương thức route sẵn có
1.2.
1
Tham số Route
2
1.2.1.
Tham số bắt buộc
2
1.2.2.
Tham số tùy chọn
2
1.2.3.
Các ràng buộc về biểu thức chính quy
2
1.2.3.1. Ràng buộc toàn cục (global constraints).............................................3 1.2.4.
Named Route 3
1.2.4.1. Nhóm route và các route được đặt tên................................................4 1.2.4.2. Sinh URI cho các route được đặt tên..................................................4 1.3.
Nhóm route 4
1.3.1.
Middleware 5
1.3.2.
Namespaces 5
1.3.3.
Sub-Domain Routing
1.3.4.
Tiền tố route (route prefix) 6
1.4.
5
Ngăn chặn CSRF 6
1.4.1.
Giới thiệu
6
1.4.2.
Loại bỏ URI từ CSRF protection 7
1.4.3.
X-CSRF-TOKEN
7
1.5.
X-XSRF-TOKEN 8
1.6.
Route Model Binding
1.6.1.
8
Ràng buộc ngầm định (Implicit Binding) 8
1.6.1.1. Tùy biến tên khóa...............................................................................8 1.6.2.
Ràng buộc tường minh (Explicit Binding) 9
1.6.2.1. Ràng buộc một tham số vào một model..............................................9 1.6.2.2. Tùy biến Resolution Logic..................................................................9 1.6.2.3. Tùy biến hành động “Not Found”.....................................................10 1.7.
Form Method Spoofing
10
1.8.
Truy cập vào route hiện tại
CHƯƠNG 2.
MIDDLEWARE
11
2.1.
Giới thiệu
2.2.
Định nghĩa Middleware 11
2.2.1. 2.3.
11
Before/After Middleware
12
Đăng ký Middleware
13
2.3.1.
Global Middleware 13
2.3.2.
Gán Middleware cho routes
2.3.3.
Nhóm Middleware 14
13
2.4.
Tham số Middleware
2.5.
Terminable Middleware 16
CHƯƠNG 3.
10
15
ROUTING CONTROLLERS
3.1.
Giới thiệu
3.2.
Controllers cơ bản 17
17
17
3.2.1.1. Controllers & Namespaces...............................................................17 3.2.1.2. Đặt tên cho controller routes.............................................................18 3.3.
Controller Middleware
18
3.4.
RESTful Resource Controllers 19 3.4.1.1. Các hành động xử lý bởi resource controller....................................19 3.4.1.2. Partial Resource Routes....................................................................20 3.4.1.3. Đặt tên Resource Routes...................................................................20 3.4.1.4. Đặt tên Resource Route Parameters..................................................20 3.4.1.5. Bổ sung Resource Controllers...........................................................21
4.1.1.2. Lấy phương thức request..................................................................27 4.1.2. 4.2.
PSR-7 Request
27
Lấy thông tin Input
27
4.2.1.
Lấy một giá trị input 27
4.2.2.
Lấy giá trị JSON input
4.2.3.
Xác định sự hiện hữu của một giá trị
4.2.4.
Lấy toàn bộ dữ liệu input
4.2.5.
Lấy một phần dữ liệu input 28
4.2.6.
Thuộc tính động
4.2.7.
Input cũ
28 28
28
28
28
4.2.7.1. Flash input vào session.....................................................................29 4.2.7.2. Flash input vào session rồi điều hướng.............................................29 4.2.7.3. Lấy dữ liệu cũ...................................................................................29 4.2.8.
Cookies
29
4.2.8.1. Lấy cookies từ request......................................................................29 4.2.8.2. Đính kèm một cookie mới vào một response....................................30 4.2.9.
Files 30
4.2.9.1. Lấy file được upload.........................................................................30 4.2.9.2. Kiểm tra upload thành công..............................................................30 4.2.9.3. Di chuyển file upload........................................................................30 4.2.9.4. Các phương thức khác với file..........................................................31 CHƯƠNG 5. 5.1.
RESPONSES
Response cơ bản
32
32
5.1.1.
Các đối tượng của response
32
5.1.2.
Đính kèm headers vào response
32
5.1.3.
Đính kèm cookies vào response
33
5.1.4.
Cookies và mã hóa 34
5.2.
Các kiểu response khác
5.2.1.
Xem response34
5.2.2.
JSON response
5.2.3.
Tải file
35
34
34
5.2.4. 5.3.
File response 35 Điều hướng 35
5.3.1.
Điều hướng tới named route
5.3.2.
Điều hướng tới controller actions 36
5.3.3.
Điều hướng với flashed session data
5.4.
36 36
Response macros 37
CHƯƠNG 6. 6.1.
VIEW VÀ BLADE TEMPLATES
Cơ bản về view
38
38
6.1.1.
Xác định sự tồn tại của view
6.1.2.
Dữ liệu trong view 39
38
6.1.2.1. Truyền dữ liệu vào view...................................................................39 6.1.2.2. Chia sẽ dữ liệu với toàn bộ view.......................................................39 6.1.3.
View composers
40
6.1.3.1. Đính kèm một composer vào nhiều view..........................................42 6.1.3.2. View creators....................................................................................42 6.2.
Blade Templates
6.2.1.
Giới thiệu
6.2.2.
Kế thừa template
43
43 43
6.2.2.1. Định nghĩa một layout......................................................................43 6.2.2.2. Mở rộng một layout..........................................................................43 6.2.3.
Hiển thị dữ liệu
44
6.2.3.1. Blade và JavaScript Framework.......................................................45 6.2.3.2. Echo dữ liệu nếu tồn tại....................................................................45 6.2.3.3. Hiển thị dữ liệu unescaped................................................................45 6.2.4.
7.1.1.1. Giới thiệu..........................................................................................51 7.1.1.2. Chạy các Raw SQL query.................................................................53 7.1.1.3. Giao tác trong cơ sở dữ liệu..............................................................55 7.1.1.4. Sử dụng nhiều kết nối.......................................................................56 7.1.2.
Query Builder
56
7.1.2.1. Giới thiệu..........................................................................................56 7.1.2.2. Truy xuất kết quả..............................................................................56 7.1.2.3. Selects...............................................................................................59 7.1.2.4. Joins..................................................................................................59 7.1.2.5. Unions...............................................................................................61 7.1.2.6. Mệnh đề Where.................................................................................61 7.1.2.7. Mệnh đề Where nâng cao.................................................................63 7.1.2.8. Mệnh đề JSON Where......................................................................64 7.1.2.9. Sắp xếp, nhóm, giới hạn và offset.....................................................65 7.1.2.10. Câu điều kiện..................................................................................66 7.1.2.11. Inserts.............................................................................................66 7.1.2.12. Updates...........................................................................................67
7.1.3.1. Giới thiệu..........................................................................................68 7.1.3.2. Tạo các Migration.............................................................................68 7.1.3.3. Cấu trúc của Migration.....................................................................69 7.1.3.4. Chạy các Migration...........................................................................70 7.1.3.5. Viết các Migration............................................................................70
7.1.4.
Seeding
78
7.1.4.1. Giới thiệu..........................................................................................78 7.1.4.2. Tạo Seeder........................................................................................78 7.1.4.3. Chạy các Seeder................................................................................80 7.2.
Eloquent ORM
7.2.1.
Mở đầu
80
80
7.2.1.1. Giới thiệu..........................................................................................80 7.2.1.2. Định nghĩa các mô hình....................................................................80 7.2.1.3. Truy xuất nhiều mô hình...................................................................83 7.2.1.4. Truy xuất mô hình đơn/ gộp nhóm....................................................85 7.2.1.5. Thêm và cập nhật mô hình................................................................86 7.2.1.6. Xóa mô hình.....................................................................................89 7.2.1.7. Phạm vi truy vấn...............................................................................92 7.2.1.8. Các sự kiện.......................................................................................96 7.2.2.
Các quan hệ 97
7.2.2.1. Giới thiệu..........................................................................................97 7.2.2.2. Định nghĩa các quan hệ.....................................................................97 7.2.2.3. Truy vấn các quan hệ......................................................................111 7.2.2.4. Thêm các mô hình liên quan...........................................................115 7.2.2.5. Quan hệ nhiều – nhiều....................................................................117 7.2.3.
Collections
119
7.2.3.1. Giới thiệu........................................................................................119
7.2.3.2. Các phương thức sẵn có..................................................................120 7.2.3.3. Custom Collections.........................................................................120 7.2.4.
Mutators
121
7.2.4.1. Giới thiệu........................................................................................121 7.2.4.2. Accessors & Mutators.....................................................................121 7.2.4.3. Date Mutators.................................................................................123 7.2.4.4. Attribute Casting.............................................................................124 7.2.5.
Serialization 125
7.2.5.1. Giới thiệu........................................................................................125 7.2.5.2. Sử dụng cơ bản...............................................................................126 7.2.5.3. Ẩn các thuộc tính khỏi JSON..........................................................126 7.2.5.4. Thêm giá trị vào JSON...................................................................127 CHƯƠNG 8. 8.1.
SERVICES 129
Xác Thực (Authentication)
129
8.1.1.
Giới thiệu
8.1.2.
Bắt đầu nhanh với xác thực 129
8.1.3.
Xác thực người dùng thủ công
133
8.1.4.
Xác thực cơ bản trong HTTP
136
8.1.5.
Đặt lại mật khẩu
8.1.6.
Thêm Custom User Providers
8.1.7.
Events 143
8.2.
129
Authorization
137
144
8.2.1.
Giới thiệu
8.2.2.
Định nghĩa Abilities 144
8.2.3.
Kiểm tra Abilities
8.2.4.
Bên trong Blade Templates 148
8.2.5.
Policies
8.2.6.
Controller Authorization
8.3.
144 146
149 153
Cache 154
8.3.1.
Cấu hình
8.3.2.
Sử dụng Cache
8.3.3.
Cache Tags 159
8.3.4.
Thêm các cache driver tùy chọn
8.3.5.
Events 161
8.4.
140
154 156
Errors & Logging 162
8.4.1.
Giới thiệu
162
8.4.2.
Cấu hình
162
8.4.3.
The Exception Handler
8.4.4.
HTTP Exceptions
8.4.5.
Logging
165
165
163
159
8.5.
Events
166
8.5.1.
Giới thiệu
166
8.5.2.
Registering Events / Listeners
8.5.3.
Định nghĩa event
8.5.4.
Định nghĩa listener 168
8.5.5.
Tạo Events
8.5.6.
Broadcasting Events 171
8.5.7.
Event Subscriber
8.6.
168
171 176
Filesystem / Cloud Storage
8.6.1.
Giới thiệu
177
8.6.2.
Cấu hình
178
8.6.3.
Sử dụng cơ bản
8.6.4.
Custom Filesystems 182
8.7.
166
177
179
Localization 184
8.7.1.
Giới thiệu
8.7.2.
Sử dụng cơ bản
8.7.3.
Ghi đè file ngôn ngữ của nhà cung cấp
8.8.
184 185
Mail 186
8.8.1.
Giới thiệu
186
8.8.2.
Gửi Mail
188
8.8.3.
Mail & Local Development 192
8.8.4.
Events 192
8.9.
186
Hàng đợi (queue) 193
8.9.1.
Giới thiệu
8.9.2.
Viết các lớp công việc
8.9.3.
Đưa công việc vào hàng đợi
8.9.4.
Thực thi bộ lắng nghe hàng đợi (queue listener) 201
8.10.
193
Phiên (session)
8.10.1. Giới thiệu
196
206
206
8.10.2. Sử dụng cơ bản
208
8.10.3. Thêm driver phiên
210
8.11.
193
Task Scheduling (Lap lich cho tác vụ) 212
8.11.1. Giới thiệu
212
8.11.2. Định nghĩa lịch
212
8.11.3. Đầu ra của tác vụ
216
8.11.4. Task Hooks 8.12.
216
Kiểm tra (Testing) 217
8.12.1. Giới thiệu
217
8.12.2. Kiểm thử ứng dụng 218 8.12.3. Làm việc với cơ sở dữ liệu 222 8.12.4. Mocking 8.13.
227
Xác nhận(Validation)
8.13.1. Giới thiệu
230
230
8.13.2. Xác nhận Quickstart 230 8.13.3. Các phương pháp xác nhận khác 235 8.13.4. Làm việc với các thông báo lỗi 8.13.5. Quy tắc Xác thực Có sẵn
241
8.13.6. Điều kiện Thêm Quy tắc
248
8.13.7. Quy tắc xác thực tùy chỉnh 249
239
CHƯƠNG 1. ROUTING 1.1. Cơ bản về Routing Các route của Laravel được định nghĩa trong file app/Http/routes.php, được tự
động tải bởi framework. Các route cơ bản nhất của Laravel đơn thuần chấp nhận một URI và một Closure, cung cấp một phương thức vô cùng đơn giản và có ý nghĩa để định nghĩa route: Route::get('foo', function () { return 'Hello World'; }); 1.1.1. File ruote mặc định File route mặc định route.php sẽ được gọi bởi RouteServiceProvider và được tự động thêm vào trong web middleware group, cung cấp truy cập tới trạng thái phiên và CSRF protection. Hầu hết các route cần cho ứng dụng đều được định nghĩa bên trong file này. 1.1.2. Các phương thức route sẵn có Router cho phép người dùng đăng ký các route có khả năng phản hồi HTTP verb bất kỳ 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 lúc người dùng cần đăng ký một route phản hồi tới nhiều HTTP verb. Để thực hiện việc này ta sử dụng phương thức match. Hoặc ta có thể đăng ký một route phản hồi tới mọi HTTP verbs sử dụng phương thức any: Route::match(['get', 'post'], '/', function () { // }); Route::any('foo', function () { // });
1
1.2. Tham số Route 1.2.1. Tham số bắt buộc Đôi khi người dùng cần lấy ra một số phần của URI trong route. Ví dụ bạn cần lấy ID người dùng trong URI. Khi đó bạn cần định nghĩa tham số route: Route::get('user/{id}', function ($id) { return 'User '.$id; }); Bạn có thể định nghĩa số lượng tham số bất kỳ mà route của bạn yêu cầu: Route::get('posts/{post}/comments/{comment}',function($postId, $commentId) { // }) Tham số route luôn được để trong ngoặc tròn. Các tham số được truyền vào Closure của route khi route được thực hiện. Chú ý: Tham số route không thể chứa ký hiệu “-“. Cần sử dụng “_” để thay thế. 1.2.2. Tham số tùy chọn Đôi khi bạn cần chỉ định một tham số route, nhưng mong muốn tham số đó là tùy chọn. Việc này có thể thực hiện qua việc đặt dấu ? phía sau tên tham số. Chắc chắn rằng bạn đã gán cho biến tương ứng của route một giá trị mặc định: Route::get('user/{name?}', function ($name = null) { return $name; }); Route::get('user/{name?}', function ($name = 'John') { return $name; }); 1.2.3. Các ràng buộc về biểu thức chính quy Bạn có thể ràng buộc định dạng của tham số route sử dụng phương thức where
trên một route instance. Phương thức where chấp nhận tên của tham số và một biểu thức chính quy định nghĩa tham số đó bị ràng buộc như thế nào: Route::get('user/{name}', function ($name) { // }) ->where('name', '[A-Za-z]+'); 2
Route::get('user/{id}', function ($id) { // }) ->where('id', '[0-9]+'); Route::get('user/{id}/{name}', function ($id, $name) { // }) ->where(['id' => '[0-9]+', 'name' => '[a-z]+']); 1.2.3.1. Ràng buộc toàn cục (global constraints) Nếu bạn muốn một tham số route luôn luôn bị ràng buộc bởi một biểu thức chính quy cho trước, bạn có thể sử dụng phương thức pattern. Bạn cần định nghĩa các pattern này trong phương thức boot của RouteServiceProvider: /**Define your route model bindings, pattern filters, etc. * @param \Illuminate\Routing\Router $router * @return void */ public function boot(Router $router) { $router->pattern('id', '[0-9]+'); parent::boot($router); }
Một khi pattern đã được định nghĩa, nó sẽ tự động được áp dụng cho tất cả các route sử dụng tên tham số đó: Route::get('user/{id}', function ($id) { // Only called if {id} is numeric. }); 1.2.4. Named Route Các route được đặt tên cho phép sinh URI một cách thuận tiện hoặc điều hướng đối với một số route. Bạn có thể đặt tên cho một route sử dụng as array key khi định nghĩa route: Route::get('user/profile', ['as' => 'profile', function () { // }]); 3
Bạn cũng có thể chỉ định tên route cho các hành động của controller: Route::get('user/profile', [ 'as' => 'profile', 'uses' => 'UserController@showProfile' ]); Hoặc thay vì chỉ định tên route trong phần định nghĩa mảng route, bạn có thể nối thêm phương thức name vào cuối phần định nghĩa route: Route::get('user/profile', 'UserController@showProfile')->name('profile'); 1.2.4.1. Nhóm route và các route được đặt tên Nếu bạn đang sử dụng các nhóm route, bạn cần chỉ định một từ khóa as trong mảng thuộc tính của nhóm route, mảng này cho phép bạn thiết đặt một tiền tố tên route chung cho tất cả các route trong nhóm: Route::group(['as' => 'admin::'], function () { Route::get('dashboard', ['as' => 'dashboard', function () { // Route named "admin::dashboard" }]);
}); 1.2.4.2. Sinh URI cho các route được đặt tên Một khi bạn đã gán tên cho một route cho trước, bạn có thể sử dụng tên đó để sinh URI hoặc điều hướng thông qua hàm toàn cục route: // Generating URLs... $url = route('profile'); // Generating Redirects... return redirect()->route('profile'); Nếu route đã được đặt tên có định nghĩa tham số, bạn có thể truyền các tham số đó như là đối số của hàm route. Các tham số đó sẽ được tự động chèn vào vị trí thích hợp trong URI: Route::get('user/{id}/profile', ['as' => 'profile', function ($id) { // }]); $url = route('profile', ['id' => 1]); 1.3. Nhóm route Nhóm route cho phép chia sẻ các thuộc tính route, ví dụ như middleware hoặc namespaces, giữa số lượng lớn các route mà không cần định nghĩa các thuộc tính này 4
trên từng route. Các thuộc tính được chia sẻ được chỉ định dưới dạng mảng và mảng này là tham số thứ nhất của phương thức Route::group. 1.3.1. Middleware Để gán middleware cho toàn bộ các route trong một nhóm, bạn có thể sử dụng từ khóa middleware trong mảng thuộc tính của nhóm. Middleware sẽ được thực thi theo thứ tự bạn định nghĩa mảng này: Route::group(['middleware' => 'auth'], function () { Route::get('/', function () { // Uses Auth Middleware
}); Route::get('user/profile', function () { // Uses Auth Middleware }); }); 1.3.2. Namespaces Một trường hợp sử dụng khác của nhóm route là gán cùng một PHP namespace cho một nhóm các controller. Bạn có thể dùng tham số namespace trong mảng thuộc tính của nhóm để chỉ định namespace cho toàn bộ controller trong nhóm: Route::group(['namespace' => 'Admin'], function() { // Controllers Within The "App\Http\Controllers\Admin" Namespace Route::group(['namespace' => 'User'], function() { // Controllers Within The "App\Http\Controllers\Admin\User" Namespace }); }); Mặc định RouteServiceProvider sẽ bao gồm file route.php trong một nhóm namespace, cho phép bạn đăng ký controller routes mà không cần chỉ rõ toàn bộ tiền tố namespace App\Http\Controllers. Do đó, chúng ta chỉ cần chỉ rõ phần namespace phía sau namespace gốc App\Http\Controllers. 1.3.3. Sub-Domain Routing Nhóm rout có thể được sử dụng để định tuyến wildcard sub-domains. Subdomains có thể được gán cho tham số route cũng giống như route URI, cho phép bạn lấy một phần của sub-domain để sử dụng trong rout hoặc controller của bạn. Sub5
domain có thể được chỉ định trong mảng thuộc tính của nhóm sử dụng từ khóa domain: Route::group(['domain' => '{account}.myapp.com'], function () { Route::get('user/{id}', function ($account, $id) {
// }); }); 1.3.4. Tiền tố route (route prefix) Thuộc tính prefix của nhóm có thể được sử dụng để thêm vào đầu mỗi route trong nhóm với URI cho trước. Ví dụ, bạn có thể muốn thêm tiền tố toàn bộ route URI trong nhóm với từ khóa admin: Route::group(['prefix' => 'admin'], function () { Route::get('users', function () { // Matches The "/admin/users" URL }); }); Bạn cũng có thể sử dụng tham số prefix để chỉ định các tham số chung cho các route đã được nhóm: Route::group(['prefix' => 'accounts/{account_id}'], function () { Route::get('detail', function ($accountId)
{
// Matches The "/accounts/{account_id}/detail" URL }); }); 1.4. Ngăn chặn CSRF 1.4.1. Giới thiệu Laravel giúp dễ dàng bảo vệ ứng dụng khỏi các tấn công kiểu cross-site request forgery (CSRF). CSRF là một kiểu cố ý lợi dụng nhờ đó các câu lệnh không được chứng thực lại được thực thi bởi người dùng được chứng thực. Laravel tự động sinh một CSRF “token” cho mỗi phiên làm việc đang hoạt động của người dùng được quản lý bởi ứng dụng. Token này được sử dụng để xác minh rằng người dùng được chứng thực là chủ thể thực sự gửi yêu cầu tới ứng dụng. Mỗi khi bạn định nghĩa một HTML
form trong ứng dụng, bạn cần bao gồm một trường CSRF token ẩn trong form để CSRF protection middleware sẽ có thể xác nhận tính hợp lệ của yêu cầu. Để sinh một 6
trường đầu vào ẩn _token có chứ CSRF token, bạn có thể sử dụng hàm trợ giúp csrf_field: // Vanilla PHP <?php echo csrf_field(); ?> // Blade Template Syntax {{ csrf_field() }} Hàm này sẽ sinh đoạn HTML sau:
'stripe/*', ]; } 1.4.3. X-CSRF-TOKEN Ngoài việc kiểm tra CSRF token như là một tham số POST, VerifyCsrfToken middleware của Laravel cũng sẽ kiểm tra X-CSRF-TOKEN request header. Ví dụ bạn có thể lưu trữ token này trong một “meta” tag: <meta name="csrf-token" content="{{ csrf_token() }}"> 7
Một khi bạn đã tạo meta tag, bạn có thể chỉ dẫn một thư viện như jQuery để them tonken vào toàn bộ các request header. Điều này giúp ngăn chặn CSRF một cách đơn giản, thuận tiện với các ứng dụng AJAX: $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); 1.5. X-XSRF-TOKEN Laravel cũng lưu trữ mã thông báo CSRF trong cookie XSRF-TOKEN. Bạn có thể sử dụng giá trị cookie để đặt tiêu đề yêu cầu X-XSRF-TOKEN. Một số frameworks JavaScript, như Angular, tự động thực hiện việc này cho bạn. Bạn không cần phải sử dụng giá trị này theo cách thủ công. 1.6. Route Model Binding Laravel route model binding cung cấp một phương thức thuận tiện để đẩy các model instance vào các route của bạn. Ví dụ, thay vì đẩy vào user ID, bạn có thể đẩy toàn bộ user model instance của ID tương ứng vào route. 1.6.1. Ràng buộc ngầm định (Implicit Binding) Laravel tự động xử lý các Eloquent model có khả năng gợi ý (type-hinted) được
định nghĩa trong route hoặc hành động của controller, là những nơi có tên biến trùng với một route segment name. Ví dụ: Route::get('api/users/{user}', function (App\User $user) { return $user->email; }); Trong ví dụ này, vì Eloquent đã gợi ý biến $user được định nghĩa trong route phù hợp với {user} segment trong URI của route, Laravel sẽ tự động đẩy model instance có ID trùng với giá trị tương ứng từ request URI. Nếu một model instance phù hợp không được tìm thấy trong cơ sở dữ liệu, một phản hồi 404 HTTP sẽ tự động được tạo ra. 1.6.1.1. Tùy biến tên khóa Nếu bạn muốn implicit model binding sử dụng một cột trong cơ sở dữ liệu mà không dùng id khi truy xuất model, bạn có thể ghi đè lên phương thức getRouteKeyName trong Eloquent model của bạn: 8
/** Get the route key for the model. * @return string */ public function getRouteKeyName() { return 'slug'; } 1.6.2. Ràng buộc tường minh (Explicit Binding) Để đăng ký một explicit binding, sử dụng phương thức model của router để chỉ định lớp cho một tham số có sẵn. Bạn nên định nghĩa model bindings của bạn trong phương thức RouteServiceProvider::boot: 1.6.2.1. Ràng buộc một tham số vào một model
public function boot(Router $router) { parent::boot($router); $router->model('user', 'App\User'); } Tiếp theo, định nghĩa một route chứa tham số {user}: $router->get('profile/{user}', function(App\User $user) { // }); Vì chúng ta đã ràng buộc tham số {user} vào App\User model, một User instance sẽ được đẩy vào route. Do đó, ví dụ, một yêu cầu tới sẽ truyền instance có ID là 1. Nếu một model instance phù hợp không được tìm thấy trong cơ sở dữ liệu, một phản hồi 404 HTTP sẽ tự động được tạo ra. 1.6.2.2. Tùy biến Resolution Logic Nếu bạn muốn sử dụng resolution logic của mình, bạn nên dùng phương thức Route::bind. Closure mà bạn truyền vào phương thức bind sẽ nhận được giá trị của URI segment, và trả về instance của lớp mà bạn muốn truyền vào route: $router->bind('user', function ($value) { return App\User::where('name', $value)->first(); }); 9
1.6.2.3. Tùy biến hành động “Not Found” Nếu bạn muốn chỉ định hành động “not found” của riêng mình, truyền vào Closure như là đối số thứ ba của phương thức model: $router->model('user', 'App\User', function () { throw new NotFoundHttpException; }); 1.7. Form Method Spoofing
HTML forms không hỗ trợ các phương thức PUT, PATCH hoặc DELETE. Vì vậy, khi định nghĩa các PUT, PATCH hoặc DELETE route được gọi từ một HTML form, bạn cần thêm một trường ẩn _method vào form. Giá trị được gửi cùng trường _method sẽ được sử dụng như một phương thức yêu cầu: <form action="/foo/bar" method="POST"> <input type="hidden" name="_method" value="PUT"> <input type="hidden" name="_token" value="{{ csrf_token() }}"> </form> Để tạo ra trường ẩn _method bạn cũng có thể sử dụng helper function: <?php echo method_field('PUT'); ?> Hoặc sử dụng Blade template engine: {{ method_field('PUT') }} 1.8. Truy cập vào route hiện tại Phương thức Route::current() sẽ trả về route đang xử lý yêu cầu HTTP hiện tại, cho phép bạn xem đầy đủ Illuminate\Routing\Route instance: $route = Route::current(); $name = $route->getName(); $actionName = $route->getActionName() Bạn cũng có thể sử dụng các helper method currentRouteName và currentRouteAction trong lớp để truy cập tên hoặc hành động của route hiện tại: $name = Route::currentRouteName(); $action = Route::currentRouteAction();
10
CHƯƠNG 2. MIDDLEWARE 2.1. Giới thiệu Middleware cung cấp một cơ chế thuận tiện để lọc các HTTP requests được gửi tới ứng dụng của bạn. Ví dụ, Laravel chứa một middleware kiểm tra người dùng ứng
dụng là xác thực. Nếu người dùng không xác thực, middleware sẽ điều hướng người dùng trở lại màn hình đăng nhập. Tuy nhiên, nếu người dùng là xác thực, middleware cho phép request tiếp tục được thực hiện trên ứng dụng. Tất nhiên, middleware có thể được viết thêm để thực hiện nhiều tác vụ khác bên cạnh việc xác thực. Một CORS middleware có trách nhiệm thêm headers thích hợp vào tất cả các response được gửi từ ứng dụng của bạn. Một logging middleware có thể ghi log toàn bộ request được gửi tới. Laravel framework cung cấp một số middleware, bao gồm middleware cho việc bảo trì, xác thực, CSRF protection, v.v… Toàn bộ các middleware này được đặt trong thư mục app/Http/Middleware. 2.2. Định nghĩa Middleware Để tạo một middleware, ta sử dụng câu lệnh Artisan make:middleware: php artisan make:middleware AgeMiddleware Câu lệnh này sẽ đặt một lớp AgeMiddleware mới vào thư mục app/Http/Middleware của bạn. Trong middleware này, chúng ta chỉ cho phép truy cập vào route nếu giá trị age truyền vào có giá trị lớn hơn 200. Ngược lại, ta sẽ chuyển hướng users về “home” URI. namespace App\Http\Middleware; use Closure; class AgeMiddleware { /** Run the request filter. * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if ($request->input('age') <= 200) { 11
return redirect('home'); } return $next($request); } } Như đã thấy, nếu giá trị age nhỏ hơn hoặc bằng 200, middleware sẽ trả về một HTTP điều hướng tới client; ngược lại, request được sẽ được xử lý tiếp. Để gửi request vào sâu hơn trong ứng dụng (cho phép middleware thực hiện “pass”), chỉ cần gọi callback $next bằng $request. Middleware được hình dung như một chuỗi các “layer” mà HTTP request cần vượt qua trước khi chúng vào được ứng dụng. Mỗi layer có thể kiểm tra request, thậm chí từ chối request hoàn toàn 2.2.1. Before/After Middleware Một middleware được chạy trước hay sau một request phụ thuộc vào chính middleware đó. Ví dụ, middleware dưới đây có thể thực hiện một vài tác vụ trước khi request được xử lý bởi ứng dụng: namespace App\Http\Middleware; use Closure; class BeforeMiddleware { public function handle($request, Closure $next) { // Perform action return $next($request); } } Tuy nhiên, middleware này cũng có thể thực hiện tác vụ của mình sau khi ứng
dụng xử lý câu request: namespace App\Http\Middleware; use Closure; class AfterMiddleware 12
{ public function handle($request, Closure $next) { $response = $next($request); // Perform action return $response; } } 2.3. Đăng ký Middleware 2.3.1. Global Middleware Nếu bạn muốn một middleware chạy trong mọi HTTP request tới ứng dụng, chỉ cần đưa lớp middleware đó trong thuộc tính $middleware của class app/Http/Kernel.php. 2.3.2. Gán Middleware cho routes Nếu bạn muốn gán middleware cho các route nhất định, trước tiên cần đẩy middleware đó vào file app/Http/Kernel.php. Mặc định, thuộc tính $routeMiddleware của class này chứa các entry cho middleware có trong Laravel. Để thêm middleware của bạn, chỉ cần thêm nó vào danh sách và gán từ khóa bạn chọn Vi du: // Within App\Http\Kernel Class... protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic'=>\Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, ]; Một khi middleware đã được định nghĩa trong HTTP kernel, bạn có thể sử dụng từ khóa middleware trong mảng các tùy chọn của route: Route::get('admin/profile', ['middleware' => 'auth', function () { // }]); Sử dụng một mảng để gán cùng lúc nhiều middleware cho route: 13
Route::get('/', ['middleware' => ['first', 'second'], function () { // }]); Thay bằng việc sử dụng mảng, bạn cũng có thể đưa phương thức middleware vào định nghĩa route: Route::get('/', function () { // })->middleware(['first', 'second']); Khi gán middleware, bạn cũng có thể đưa vào tên đầy đủ: use App\Http\Middleware\FooMiddleware; Route::get('admin/profile', ['middleware' => FooMiddleware::class, function () { // }]); 2.3.3. Nhóm Middleware Đôi khi bạn cần nhóm một vài middleware vào một từ khóa đơn để gán chúng
vào route một cách dễ dàng hơn. Bạn có thể làm việc này thông qua thuộc tính $middlewareGroups của HTTP kernel. Mặc định, Laravel cung cấp các nhóm middleware web và api chứa cácmiddleware mà bạn thường sử dụng cho web UI và route: /**The application's route middleware groups. * @var array */ protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, ], 'api' => [ 'throttle:60,1', 14
'auth:api', ], ]; Nhóm middleware có thể được gán cho route và controller actions sử dụng cùng cú pháp như khi gán một middleware đơn. Nhóm middleware đơn giản hóa việc gán nhiều middleware cho route trong một lần: Route::group(['middleware' => ['web']], function () { // }); Nhóm web được tự động áp dụng vào file routes.php của bạn thông qua
RouteServiceProvider. 2.4. Tham số Middleware Middleware có thể nhận các tham số truyền vào. Ví dụ, ứng dụng của bạn cần kiểm tra rằng user xác thực có một “role” cho sẵn trước khi thực hiện một công việc nào đó, bạn có thể tạo một RoleMiddleware để nhận tên role như một tham số truyền vào các tham số phụ được truyền vào middleware sau đối số $next: namespace App\Http\Middleware; use Closure; class RoleMiddleware { /**Run the request filter. * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string $role * @return mixed */ public function handle($request, Closure $next, $role) { if (! $request->user()->hasRole($role)) { // Redirect... } return $next($request); 15