Mục lục
Mục lục này tương ứng với mục lục trên trang chủ của Laravel.
-
Mở đầu
- Release Notes
- Upgrade Guide
- Contribution Guide
- API Documentation
-
Thiết lập
-
Hướng dẫn
-
Cơ bản
- Routing
- Middleware
- Controllers
- Requests
- Responses
- Views
- Blade Templates
-
Nền tảng kiến trúc
-
Services
- Authentication
- Authorization
- Artisan Console
- Billing
- Cache
- Collections
- Elixir
- Encryption
- Errors & Logging
- Events
- Filesystem & Cloud Storage
- Hashing
- Helpers
- Localization
- Package Development
- Pagination
- Queues
- Redis
- Envoy or SSH Tasks
- Task Scheduling
- Testing
- Validation
-
Database
- Getting Started
- Query Builder
- Migrations
- Seeding
-
Eloquent ORM
HTTP Controllers
- Giới thiệu
- Controller cơ bản
- Controller Middleware
- RESTful Resource Controllers
- Dependency Injection & Controllers
- Route Caching
Giới thiệu
Thay vì định nghĩa tất cả logic xử lý request của bạn ở file routes.php
, thì bạn có thể muốn quản lý việc này bằng cách sử dụng các lớp Controller. Các Controller có thể nhóm các request HTTP có logic liên quan vào cùng một lớp. Các Controller được chứa tại thư mục app/Http/Controllers
.
Controllers cơ bản
Dưới đây là một ví dụ về lớp Controller cơ bản. Tất cả các Controller nên là class mở rộng của base Controller đi kèm trong bản cài đặt mặc định của Laravel:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*
* @param int $id
* @return Response
*/
public function showProfile($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
Chúng ta có thể định tuyến (route) đến một hoạt động của controller như sau:
Route::get('user/{id}', 'UserController@showProfile');
Bây giờ, khi mà một request khớp với URI của định tuyến đã được xác định, thì method showProfile
của lớp UserController
sẽ được thực thi. Tất nhiên, tham số của định tuyến cũng sẽ được truyền đến method.
Controllers & Namespaces
Có điều rất quan trọng cần lưu ý rằng chúng ta không cần phải ghi rõ không gian tên đầy đủ của controller khi định nghĩa định tuyến cho controller. Chúng ta chỉ cần định nghĩa phần tên lớp mà theo sau không gian tên "root" App\Http\Controllers
. Mặc định, RouteServiceProvider
sẽ tải file route.php
trong nhóm định tuyến chứa không gian tên gốc controller.
Nếu bạn muốn gộp hoặc sắp xếp các controller của bạn sử dụng không gian tên của PHP sâu hơn trong thư mục App\Http\Controllers
, thì đơn giản chỉ cần định nghĩa tên lớp tương đối so với không gian tên gốc App\Http\Controllers
. Do dó, nếu tên lớp controller đầy đủ của bạn là App\Http\Controllers\Photos\AdminController
, thì bạn chỉ đăng ký route như sau:
Route::get('foo', 'Photos\AdminController@method');
Naming Controller Routes
Giống như định tuyến đóng kín (closure), bạn có thể đặt tên cho định tuyến controller:
Route::get('foo', ['uses' => 'FooController@method', 'as' => 'name']);
Bạn cũng có thể dùng phương thức trợ giúp route
để sinh ra URL cho một định tuyến controller đã được đặt tên:
$url = route('name');
Controller Middleware
Middleware may be assigned to the controller's routes like so: Middleware có thể được gán cho định tuyến của controller như sau:
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'UserController@showProfile'
]);
Tuy nhiên, sẽ là tiện lợi hơn nếu như định nghĩa middleware từ trong hàm contructor của controller. Sử dụng method middleware
từ trong controller của bạn, bạn có thể dễ dàng gán middleware cho controller. Bạn thậm chí có thể hạn chế middleware cho một vài method cụ thể trong lớp controller:
class UserController extends Controller
{
/**
* Instantiate a new UserController instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log', ['only' => [
'fooAction',
'barAction',
]]);
$this->middleware('subscribed', ['except' => [
'fooAction',
'barAction',
]]);
}
}
RESTful Resource Controllers
Những resource controller làm cho việc xây dựng các RESTful controller xung quanh các nguồn tài nguyển trở nên dễ dàng hơn. Ví dụ như, bạn có thể muốn tạo một controller xử lý những HTTP request liên quan đến "photos" được lưu trữ trong ứng dụng của bạn. Sử dụng câu lệnh Artisan make:controller
, chúng ta có thể nhanh chóng tạo ra controller:
php artisan make:controller PhotoController --resource
Câu lệnh Artisan sẽ tạo ra file controller tại app/Http/Controllers/PhotoController.php
. Controller sẽ bao gồm method cho các hoạt động của tài nguyên sẵn có.
Tiếp theo, bạn có thể muốn đăng ký một định tuyến đa tài nguyên cho controller:
Route::resource('photo', 'PhotoController');
Khai báo định tuyến duy nhất này tạo ra nhiều định tuyến để xử lý đa dạng các loại hành động RESTful cho tài nguyên "photo". Tương tự như vậy, controller được tạo ra sẽ có sẵn vài method gốc rễ cho từng hành động, bao gồm cả ghi chú thông báo cho bạn những URI và những HTTP method (POST, GET, PUT, PATCH, DELETE) nào chúng xử lý.
Những hành động được xử lý bởi Resource Controller
Verb | Path | Action | Route Name
----------|-----------------------|--------------|---------------------
GET | /photo
| index | photo.index
GET | /photo/create
| create | photo.create
POST | /photo
| store | photo.store
GET | /photo/{photo}
| show | photo.show
GET | /photo/{photo}/edit
| edit | photo.edit
PUT/PATCH | /photo/{photo}
| update | photo.update
DELETE | /photo/{photo}
| destroy | photo.destroy
Remember, since HTML forms can't make PUT, PATCH, or DELETE requests, you will need to add a hidden _method
field to spoof these HTTP verbs:
Hãy nhớ rằng, kể từ khi những HTML form không thể tạo ra các request như PUT, PATCH, hay DELETE, thì bạn cần phải thêm một trường ẩn _method
để giả mạo những HTTP method.
<input type="hidden" name="_method" value="PUT">
Định tuyến tài nguyên thành phần
Khi khai báo một định tuyến tài nguyên, bạn có thể chỉ định một tập hợp con của các hành động để xử lý trên định tuyến:
Route::resource('photo', 'PhotoController', ['only' => [
'index', 'show'
]]);
Route::resource('photo', 'PhotoController', ['except' => [
'create', 'store', 'update', 'destroy'
]]);
Đặt tên các định tuyến tài nguyên
Mặc định, tất cả các hành động của controller tài nguyên đều có tên; tuy nhiên, bạn có thể ghi đè những tên đó bằng cách truyền thêm chuỗi names
tuỳ theo lựa chọn của bạn:
Route::resource('photo', 'PhotoController', ['names' => [
'create' => 'photo.build'
]]);
Đặt tên tham số của định tuyến tài nguyên
Mặc định, Route::resource
sẽ tạo những tham số cho các định tuyến tài nguyên của bạn dựa trên tên tài nguyên. Bạn có thể dễ dàng ghi đè cho từng resource cơ bản bằng cách truyền parameters
trong chuỗi tuỳ chọn. Chuỗi parameters
nên là một mảng kết hợp giữa tên tài nguyên và tên tham số:
Route::resource('user', 'AdminUserController', ['parameters' => [
'user' => 'admin_user'
]]);
Ví dụ trên sẽ tạo ra những URI sau cho định tuyến show
của tài nguyên:
/user/{admin_user}
Thay vì truyền một chuỗi các tên tham số, bạn có thể đơn giản truyền chữ singular
để hướng dẫn Laravel dùng tên tham số mặc định, nhưng mà làm "khác biệt hoá" chúng:
Route::resource('users.photos', 'PhotoController', [
'parameters' => 'singular'
]);
// /users/{user}/photos/{photo}
Ngoài ra, bạn có thể thiết lập tham số của định tuyến tài nguyên trở thành khác biệt toàn cục hoặc thiết lập ánh xạ toàn cục cho tên tham số tài nguyên của bạn.
Route::singularResourceParameters();
Route::resourceParameters([
'user' => 'person', 'photo' => 'image'
]);
Khi bạn tuỳ biến tên tham số tài nguyên, nhớ rằng giữ ưu tiên đặt tên là rất quan trọng:
- Những tham số truyền vào
Route::resource
phải thật rõ ràng. - Những ánh xạ tham số toàn cục phải được thiết lập thông qua
Route::resourceParameters
. - Cài đặt
singular
phải được truyền qua chuỗiparameters
đếnRoute::resource
hoặc thiết lập thông quaRoute::singularResourceParameters
. - Những hành vi mặc định.
Bổ sung controller tài nguyên
Nếu cần phải thêm những định tuyến bổ sung cho một controller tài nguyên ngoài những định tuyến tài nguyên mặc định, thì bạn nên định nghĩa những định tuyến đó trước khi gọi Route::resource
; nếu không thì những định tuyến đã được định nghĩa bởi method resource
sẽ có thể vô tình bị ưu tiên hơn những định tuyến bổ sung của bạn.
Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');
Dependency Injection & Controllers
Constructor Injection
Phần service container của Laravel được dùng để xử lý tất cả các controller của Laravel. Kết quả là, bạn có thể "type-hint" bất cứ thành phần phụ thuộc nào mà controller của bạn cần vào trong constructor của controller. Các thành phần phụ thuộc sẽ được tự động xử lý và được thêm vào trong "instance" của controller:
<?php
namespace App\Http\Controllers;
use App\Repositories\UserRepository;
class UserController extends Controller
{
/**
* The user repository instance.
*/
protected $users;
/**
* Create a new controller instance.
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
}
Of course, you may also type-hint any Laravel contract. If the container can resolve it, you can type-hint it.
Tất nhiên là bạn cũng có thể "type-hint" bất cứ Laravel contract nào. Nếu như container có thể xử lý thì bạn có thể "type-hint" nó.
Method Injection
Ngoài constructor injection, bạn cũng có thể "type-hint" các thành phần phụ thuộc trong các method của controller. Ví dụ, hãy "type-hint" instance của Illuminate\Http\Request
vào một trong những method của ta:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* Store a new user.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$name = $request->input('name');
//
}
}
Nếu như method của controller của bạn cũng chờ đợi đầu vào từ tham sổ của định tuyến, thì đơn giản là liệt kê các đối số của định tuyến vào phía sau các thành phần phụ thuộc khác. Ví dụ, nếu định tuyến của bạn được định nghĩa như sau:
Route::put('user/{id}', 'UserController@update');
Bạn vẫn có thể "type-hint" Illuminate\Http\Request
và truy cập vào tham số định tuyến của bạn id
bằng cách định nghĩa method controller của bạn như sau:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* Update the specified user.
*
* @param Request $request
* @param string $id
* @return Response
*/
public function update(Request $request, $id)
{
//
}
}
Route Caching
Note: Bộ nhớ đệm định tuyến (Route Caching) không hoạt động với các định tuyến dạng Closure. Để sử dụng bộ nhớ đệm định tuyến thì bạn cần phải chuyển các định tuyến Closure sang sử dụng các lớp controller.
Nếu như ứng dụng của bạn chỉ sử dụng các định tuyến dạng controller, thì bạn có thể sử dụng phần nâng cao của bộ nhớ đệm định tuyến của Laravel. Sử dụng bộ nhớ đệm định tuyến sẽ giảm mạng thời gian cần để đăng ký tất cả các định tuyến trong ứng dụng của bạn. Trong một vài trường hợp, việc đăng ký định tuyến của bạn có thể nhanh hơn đến 100 lần! Để tạo ra bộ nhớ định tuyến, bạn chỉ cần chạy lệnh Artisan route:cache
:
php artisan route:cache
Đó là tất cả! File bộ nhớ đệm định tuyến của bạn sẽ được sử dụng thay cho file app/Http/routes.php
. Nhớ rằng, nếu bạn thêm bất cứ route mới nào thì bạn cần phải tạo mới bộ nhớ đệm định tuyến. Do đó, bạn chỉ nên chạy câu lệnh route:cache
trong quá trình phát triển dự án.
Để xoá file bộ nhớ đệm định tuyến mà không tạo file mới, sử dụng câu lện route:clear
:
php artisan route:clear