Laravel cung cấp một số cách tiếp cận khác nhau để validate dữ liệu trong application của bạn. Mặc định, class controller base của Laravel đã sử dụng một trait ValidatesRequests
để cung các một phương thức cho validate request HTTP với nhiều rule validate mạnh mẽ.
Để tìm hiểu về các tính năng validation của Laravel, chúng ta hãy xem một ví dụ về validation cho một form và cách hiển thị thông báo lỗi cho người dùng.
Đầu tiên, giả sử chúng ta có các route sau đã được định nghĩa trong file routes/web.php
:
Route::get('post/create', 'PostController@create');
Route::post('post', 'PostController@store');
Dĩ nhiên, route GET
sẽ hiển thị một form cho người dùng để tạo một bài đăng mới trong blog, trong khi route POST
sẽ lưu trữ bài đăng đó vào trong blog trong cơ sở dữ liệu.
Tiếp theo, chúng ta hãy xem một controller đơn giản xử lý cho các route. Bây giờ chúng ta sẽ bỏ trống phương thức store
:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
/**
* Show the form to create a new blog post.
*
* @return Response
*/
public function create()
{
return view('post.create');
}
/**
* Store a new blog post.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// Validate and store the blog post...
}
}
Bây giờ chúng ta đã sẵn sàng để viết vào phương thức store
của chúng ta với các logic validate bài đăng trong blog. Để làm điều này, chúng ta sẽ sử dụng phương thức validate
được cung cấp trong đối tượng Illuminate\Http\Request
. Nếu pass qua validate rule, code của bạn sẽ được tiếp tục thực thi bình thường; tuy nhiên, nếu validate không thành công, một exception sẽ được đưa ra và một error response thích hợp sẽ tự động được gửi về cho người dùng. Trong trường hợp request HTTP bình thường, thì response sẽ là một chuyển hướng, còn nếu request là kiểu AJAX thì một response JSON sẽ được trả về.
Để hiểu rõ hơn về phương thức validate
, chúng ta hãy quay lại phương thứcstore
:
/**
* Store a new blog post.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// The blog post is valid...
}
Như bạn có thể thấy, chúng ta đã truyền các quy tắc validation mà chúng ta mong muốn vào phương thức validate
. Một lần nữa, nếu validation thất bại, một response thích hợp sẽ được tự động trả về. Còn nếu validation thành công, controller của chúng ta sẽ tiếp tục được thực thi bình thường.
Đôi khi bạn có thể muốn dừng chạy quy tắc validation trên một thuộc tính sau lần thất bại đầu tiên. Để làm như vậy, hãy gán quy tắc bail
cho thuộc tính:
$request->validate([
'title' => 'bail|required|unique:posts|max:255',
'body' => 'required',
]);
Trong ví dụ này, nếu quy tắc unique
trong thuộc tính title
thất bại, quy tắc max
sẽ không được kiểm tra. Các quy tắc này sẽ được validate theo thứ tự mà chúng được định nghĩa.
Nếu request HTTP của bạn chứa các tham số "lồng nhau", bạn có thể định nghĩa chúng trong quy tắc validation bằng cách sử dụng cú pháp "chấm":
$request->validate([
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);
Vậy, điều gì sẽ xảy ra nếu các tham số request không pass qua các quy tắc validation đã cho? Như đã đề cập trước đó, Laravel sẽ tự động chuyển hướng người dùng trở lại vị trí trước đó của họ. Ngoài ra, tất cả các lỗi validation sẽ được tự động flash vào trong session.
Một lần nữa, hãy lưu ý rằng chúng ta không phải liên kết bất kỳ thông báo lỗi nào với view trong route GET
của chúng ta. Điều này là do Laravel sẽ kiểm tra có lỗi trong session có hay không và tự động tạo liên kết chúng với view nếu chúng tồn tại. Biến $errors
sẽ là một instance của Illuminate\Support\MessageBag
. Để biết thêm thông tin về cách làm việc với đối tượng này, xem tài liệu của nó.
{tip} Biến
$errors
bị ràng buộc với view thông qua middlewareIlluminate\View\Middleware\ShareErrorsFromSession
, được cung cấp bởi group middlewareweb
. Khi middleware này được áp dụng, thì biến$errors
này sẽ luôn có tồn tại trong view của bạn, cho phép bạn giả sử biến$errors
luôn được khai báo và có thể được sử dụng một cách an toàn hơn.
Vì vậy, trong ví dụ của chúng ta, người dùng sẽ được chuyển hướng về phương thức create
của controller khi validation thất bại, cho phép chúng ta hiển thị các thông báo lỗi trong view như sau:
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Create Post Form -->
Mặc định, Laravel sẽ chứa hai middleware là: TrimStrings
và ConvertEmptyStringsToNull
trong stack middleware global application. Các middleware này sẽ được liệt kê trong stack bởi class App\Http\Kernel
. Vì thế, bạn sẽ cần phải đánh dấu các trường request "optional" của bạn là nullable
nếu bạn không muốn validator coi các giá trị null
của các trường này là không hợp lệ. Ví dụ:
$request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
]);
Trong ví dụ trên, chúng ta đang định nghĩa là trường publish_at
có thể là null
hoặc nếu có giá trị thì phải theo format của date. Nếu chúng ta không thêm nullable
vào trong định nghĩa quy tắc này, thì validator sẽ coi null
là một date không hợp lệ.
Trong ví dụ trên, chúng ta đã sử dụng một form bình thường để gửi dữ liệu đến application. Tuy nhiên, nhiều application sẽ sử dụng các request là AJAX. Nên nếu sử dụng phương thức validate
trong request là AJAX, thì Laravel sẽ không tạo ra response chuyển hướng. Thay vào đó, Laravel tạo ra một response JSON chứa tất cả các lỗi validation. Response JSON này sẽ được gửi về với HTTP status code là 422.
Đối với các kịch bản validation phức tạp hơn, bạn có thể tạo một "form request". Form requests là các class request tùy biến có chứa logic validation. Để tạo một class form request, hãy sử dụng lệnh Artisan CLI make:request
:
php artisan make:request StoreBlogPost
Class được tạo ra sẽ được lưu trong thư mục app/Http/Requests
. Nếu thư mục này không tồn tại, nó sẽ được tạo khi bạn chạy lệnh make:request
. Chúng ta hãy thêm một vài quy tắc validation vào phương thức rules
:
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
{tip} Bạn có thể khai báo bất kỳ phụ thuộc nào mà bạn cần trong phương thức
rule
. Những phụ thuộc đó sẽ được tự động resolve thông qua Laravel service container.
Vậy, các quy tắc validation sẽ được so sánh như thế nào? Tất cả những gì bạn cần làm là khai báo nó cho request trong phương thức controller của bạn. Form request đến sẽ được validate trước khi phương thức controller được gọi, nghĩa là bạn không cần làm lộn xộn controller của bạn với bất kỳ logic validate nào:
/**
* Store the incoming blog post.
*
* @param StoreBlogPost $request
* @return Response
*/
public function store(StoreBlogPost $request)
{
// The incoming request is valid...
// Retrieve the validated input data...
$validated = $request->validated();
}
Nếu validation thất bại, một response chuyển hướng sẽ được tạo và đưa người dùng trở về vị trí trước đó của họ. Các lỗi cũng sẽ được flash vào session để chúng có thể được hiển thị. Nếu request là loại request AJAX, response HTTP có status code 422 sẽ được trả về cho người dùng chứa một data JSON gồm các lỗi validation.
Nếu bạn muốn thêm một "after" hook vào một form request, bạn có thể sử dụng phương thức withValidator
. Phương thức này nhận vào một validator đã được khởi tạo, cho phép bạn gọi bất kỳ phương thức nào trước khi các quy tắc validation thực sự được so sánh:
/**
* Configure the validator instance.
*
* @param \Illuminate\Validation\Validator $validator
* @return void
*/
public function withValidator($validator)
{
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
}
Class form request cũng chứa một phương thức authorize
. Trong phương thức này, bạn có thể kiểm tra xem người dùng hiện tại thực sự có quyền truy cập vào resource này hay không. Ví dụ: bạn có thể xác định xem người dùng có thực sự là chủ sở hữu của một bình luận trong blog mà họ đang cố cập nhật hay không:
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$comment = Comment::find($this->route('comment'));
return $comment && $this->user()->can('update', $comment);
}
Vì tất cả các form request đều được mở rộng từ class request của Laravel, nên chúng ta có thể sử dụng phương thức user
để truy cập vào người dùng hiện tại đang được authenticate. Hãy lưu ý cách gọi đến phương thức route
trong ví dụ ở trên. Phương thức này cung cấp cho bạn quyền truy cập vào các tham số URI đã được định nghĩa trên route hiện tại, chẳng hạn như tham số {comment}
trong ví dụ bên dưới:
Route::post('comment/{comment}');
Nếu phương thức authorize
trả về false
, HTTP response có status code là 403 sẽ được tự động trả về và phương thức trong controller của bạn sẽ không được thực thi.
Nếu bạn muốn logic authorization nằm ở trong một phần khác của application, bạn hãy trả về true
từ phương thức authorize
:
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
{tip} Bạn có thể khai báo bất kỳ phụ thuộc nào mà bạn cần trong phương thức
authorize
. Những phụ thuộc đó sẽ được tự động resolve thông qua Laravel service container.
Bạn có thể tùy biến các thông báo lỗi được sử dụng bởi form request bằng cách ghi đè phương thức messages
. Phương thức này sẽ trả về một mảng gồm các cặp thuộc tính / quy tắc và các thông báo lỗi tương ứng của chúng:
/**
* Get the error messages for the defined validation rules.
*
* @return array
*/
public function messages()
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
Nếu bạn không muốn sử dụng phương thức validate
theo request, bạn có thể tự tạo một instance validator bằng cách sử dụng facade Validator
. Phương thức make
trên facade sẽ tạo ra một instance validator mới:
<?php
namespace App\Http\Controllers;
use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
/**
* Store a new blog post.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
if ($validator->fails()) {
return redirect('post/create')
->withErrors($validator)
->withInput();
}
// Store the blog post...
}
}
Tham số đầu tiên được truyền cho phương thức make
là dữ liệu cần được validation. Tham số thứ hai là các quy tắc validation sẽ được áp dụng cho dữ liệu đó.
Sau khi kiểm tra nếu request validation thất bại, bạn có thể sử dụng phương thức withErrors
để flash các thông báo lỗi vào session. Khi sử dụng phương thức này, biến $errors
sẽ được tự động chia sẻ với các view của bạn sau khi được chuyển hướng tới, cho phép bạn dễ dàng hiển thị thông báo lỗi cho người dùng. Phương thức withErrors
chấp nhận một validator và một MessageBag
hoặc một PHP array
.
Nếu bạn muốn tự tạo một validator instance nhưng vẫn muốn tận dụng tính năng chuyển hướng tự động được cung cấp bởi phương thức validate
của request, bạn có thể gọi phương thức validate
trên một validator instance đã tồn tại. Nếu validation thất bại, người dùng sẽ tự động được chuyển hướng hoặc trong trường hợp request là AJAX, thì response JSON sẽ được trả về:
Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validate();
Nếu bạn có nhiều form trong một trang, bạn có thể muốn đặt tên cho MessageBag
, để bạn có thể truy xuất vào các thông báo lỗi cho một form cụ thể. Hãy truyền tên đó làm tham số thứ hai cho phương thức withErrors
:
return redirect('register')
->withErrors($validator, 'login');
Sau đó, bạn có thể truy cập vào instance MessageBag
đã được đặt tên từ biến $errors
:
{{ $errors->login->first('email') }}
Validator cũng cho phép bạn gắn các callback sẽ được chạy sau khi validation hoàn tất. Điều này cho phép bạn dễ dàng thực hiện validation thêm hoặc thậm chí là thêm nhiều thông báo lỗi vào message collection. Để bắt đầu, hãy sử dụng phương thức after
trên một instance validator:
$validator = Validator::make(...);
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
if ($validator->fails()) {
//
}
Sau khi gọi phương thức errors
trong một instance Validator
, bạn sẽ nhận về một instance Illuminate\Support\MessageBag
, có nhiều phương thức để làm việc với các thông báo lỗi. Biến $errors
mà được tự động cung cấp cho các view cũng là một instance của class MessageBag
.
Để lấy thông báo lỗi đầu tiên cho một field, hãy sử dụng phương thức first
:
$errors = $validator->errors();
echo $errors->first('email');
Nếu bạn cần lấy tất cả các thông báo lỗi cho một field, hãy sử dụng phương thức get
:
foreach ($errors->get('email') as $message) {
//
}
Nếu bạn đang validate một mảng field, bạn có thể lấy tất cả các thông báo lỗi cho từng field trong mảng bằng ký tự *
:
foreach ($errors->get('attachments.*') as $message) {
//
}
Để lấy một mảng tất cả các thông báo lỗi cho tất cả các field, hãy sử dụng phương thức all
:
foreach ($errors->all() as $message) {
//
}
Phương thức has
có thể được sử dụng để xác định xem có tồn tại thông báo lỗi nào cho field đã cho không:
if ($errors->has('email')) {
//
}
Nếu cần, bạn có thể tùy biến thông báo lỗi cho validation thay vì mặc định. Có một số cách để định nghĩa tùy biến một thông báo lỗi. Đầu tiên, bạn có thể truyền các thông báo lỗi đã được tùy biến làm tham số thứ ba cho phương thức Validator::make
:
$messages = [
'required' => 'The :attribute field is required.',
];
$validator = Validator::make($input, $rules, $messages);
Trong ví dụ này, :attribute
sẽ được thay thế bằng tên thực sự của field mà được validation. Bạn cũng có thể sử dụng các attribute khác trong validation messages. Ví dụ:
$messages = [
'same' => 'The :attribute and :other must match.',
'size' => 'The :attribute must be exactly :size.',
'between' => 'The :attribute value :input is not between :min - :max.',
'in' => 'The :attribute must be one of the following types: :values',
];
Thỉnh thoảng bạn có thể chỉ định một thông báo lỗi tùy biến chỉ cho một field cụ thể. Bạn có thể làm như vậy bằng cách dùng ký hiệu "chấm". Chỉ định tên của attribute trước và sau đó là đến tên của quy tắc:
$messages = [
'email.required' => 'We need to know your e-mail address!',
];
Trong hầu hết các trường hợp, bạn có thể sẽ cần chỉ định các thông báo lỗi tùy biến của bạn vào trong một file language thay vì truyền chúng trực tiếp vào Validator
. Để làm như vậy, hãy thêm các thông báo lỗi của bạn vào mảng custom
trong file language resources/lang/xx/validation.php
.
'custom' => [
'email' => [
'required' => 'We need to know your e-mail address!',
],
],
Nếu bạn muốn phần :attribute
trong thông báo validation của bạn được thay thế bằng một tên attribute tùy biến, bạn có thể chỉ định tên tùy biến này trong mảng attributes
của file language resources/lang/xx/validation.php
:
'attributes' => [
'email' => 'email address',
],
Dưới đây là danh sách tất cả các quy tắc validation có sẵn và chức năng của chúng:
Accepted Active URL After (Date) After Or Equal (Date) Alpha Alpha Dash Alpha Numeric Array Bail Before (Date) Before Or Equal (Date) Between Boolean Confirmed Date Date Equals Date Format Different Digits Digits Between Dimensions (Image Files) Distinct E-Mail Exists (Database) File Filled Greater Than Greater Than Or Equal Image (File) In In Array Integer IP Address JSON Less Than Less Than Or Equal Max MIME Types MIME Type By File Extension Min Not In Not Regex Nullable Numeric Present Regular Expression Required Required If Required Unless Required With Required With All Required Without Required Without All Same Size String Timezone Unique (Database) URL
Field được validation phải là yes, on, 1 hoặc true. Điều này hữu ích để validation chấp nhận "Điều khoản dịch vụ".
Field được validation phải có bản ghi A hoặc AAAA hợp lệ theo hàm PHP dns_get_record
.
Field được validation phải là một giá trị sau một ngày nhất định. Tham số date sẽ được truyền vào hàm PHP strtotime
:
'start_date' => 'required|date|after:tomorrow'
Thay vì truyền một chuỗi date được chạy bởi hàm strtotime
, bạn có thể chỉ định một field khác để so sánh với ngày:
'finish_date' => 'required|date|after:start_date'
Field được validation phải là một giá trị sau hoặc bằng ngày đã cho. Để biết thêm thông tin, hãy xem quy tắc after.
Field được validation phải hoàn toàn là các ký tự chữ cái.
Field được validation có thể có các ký tự chữ cái và số, cũng như dấu gạch ngang và dấu gạch dưới.
Field được validation phải hoàn toàn là các ký tự chữ cái và số.
Field được validation phải là một PHP array
.
Dừng chạy các validation rule nếu lần validation đầu tiên không thành công.
Field được validation là một giá trị trước ngày đã cho. Tham số date sẽ được truyền vào hàm strtotime
của PHP.
Field được validation là một giá trị trước hoặc bằng với ngày đã cho. Tham số date sẽ được truyền vào hàm strtotime
của PHP.
Field được validation phải có kích thước ở giữa min và max đã cho. Chuỗi, số, mảng và file sẽ được so sánh theo cùng một quy tắc với quy tắc size
.
Field được validation phải có thể được cast là boolean. Input được chấp nhận là true
, false
, 1
, 0
, "1"
, và "0"
.
Field được validation phải có field là foo_confirmation
. Ví dụ: nếu field được validation là password
, thì field password_confirmation
phải có tồn tại trong input.
Field được validation phải là một ngày hợp lệ theo hàm PHP strtotime
.
Field được validation phải bằng ngày đã cho. Tham số date sẽ được truyền vào hàm strtotime
của PHP.
Field được validation phải khớp với format đã cho. Bạn nên sử dụng một trong hai date
hoặcdate_format
khi validate một field, không dùng cả hai.
Field được validation phải có giá trị khác với field.
Field được validation phải là numeric và phải có độ dài chính xác là value.
Field được validation phải có độ dài ở giữa min và max đã cho.
File được validation là một image đáp ứng các điều kiện về kích thước hoặc các quy định được tạo bởi các tham số của quy tắc:
'avatar' => 'dimensions:min_width=100,min_height=200'
Các điều kiện có thể được dùng là: min_width, max_width, min_height, max_height, width, height, ratio.
Một điều kiện ratio phải được biểu diễn dưới dạng chiều rộng chia cho chiều cao. Điều này có thể được quy định bằng một câu lệnh như 3/2
hoặc nếu float là 1.5
:
'avatar' => 'dimensions:ratio=3/2'
Vì quy tắc này yêu cầu một số tham số, nên bạn có thể sử dụng phương thức Rule::dimensions
để dễ dàng xây dựng các quy tắc:
use Illuminate\Validation\Rule;
Validator::make($data, [
'avatar' => [
'required',
Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2),
],
]);
Khi làm việc với mảng, field được validation phải không được có bất kỳ giá trị trùng lặp nào.
'foo.*.id' => 'distinct'
Field được validation phải được định dạng dưới dạng địa chỉ email.
Field được validation phải tồn tại trong một bảng cơ sở dữ liệu nhất định.
'state' => 'exists:states'
Nếu tùy chọn column
không được chỉ định, thì tên field đó sẽ được sử dụng.
'state' => 'exists:states,abbreviation'
Đôi khi, bạn có thể cần chỉ định một kết nối cơ sở dữ liệu cụ thể sẽ được sử dụng cho truy vấn exists
. Bạn có thể thực hiện điều này bằng cách thêm tên kết nối vào tên bảng thông qua cú pháp "chấm":
'email' => 'exists:connection.staff,email'
Nếu bạn muốn tùy chỉnh truy vấn được thực thi theo quy tắc validation, bạn có thể sử dụng class Rule
để dễ dàng định nghĩa các quy tắc. Trong ví dụ này, chúng ta cũng sẽ định nghĩa các quy tắc validation là một mảng thay vì sử dụng ký tự |
để phân định chúng:
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::exists('staff')->where(function ($query) {
$query->where('account_id', 1);
}),
],
]);
Field được validation phải là một tệp được tải lên thành công.
Field được validation phải không được trống khi nó có tồn tại.
Field được validation phải lớn hơn field đã cho. Hai field phải cùng loại. Các loại chuỗi, số, mảng và file sẽ được đánh giá bằng cách sử dụng các quy ước giống như quy ước của size
.
Field được validation phải lớn hơn hoặc bằng field đã cho. Hai field phải cùng loại. Các loại chuỗi, số, mảng và file sẽ được đánh giá bằng cách sử dụng các quy ước giống như quy ước của size
.
Field được validation phải là một image (jpeg, png, bmp, gif, or svg)
Field được validation phải có trong danh sách các giá trị đã cho. Vì quy tắc này thường yêu cầu bạn phải implode
một mảng, nên phương thức Rule::in
có thể được sử dụng để dễ dàng xây dựng quy tắc:
use Illuminate\Validation\Rule;
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
]);
Field được validation phải tồn tại trong các giá trị của anotherfield.
Field được validation phải là một integer.
Field được validation phải là một địa chỉ IP.
Field được validation phải là một địa chỉ IPv4.
Field được validation phải là một địa chỉ IPv6.
Field được validation phải là một chuỗi JSON.
Field được validation phải nhỏ hơn field đã cho. Hai field phải cùng loại. Các loại chuỗi, số, mảng và file sẽ được đánh giá bằng cách sử dụng các quy ước giống như quy ước của size
.
Field được validation phải nhỏ hơn hoặc bằng field đã cho. Hai field phải cùng loại. Các loại chuỗi, số, mảng và file sẽ được đánh giá bằng cách sử dụng các quy ước giống như quy ước của size
.
Field được validation phải nhỏ hơn hoặc bằng maximum của value. Chuỗi, số, mảng và file sẽ được so sánh theo cùng một quy tắc với quy tắc size
.
File được validation phải khớp với một trong các loại MIME đã cho:
'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'
Để xác định loại MIME của file được tải lên, nội dung của file sẽ được đọc và framework sẽ cố gắng đoán loại MIME, nó có thể khác với loại MIME do khách hàng cung cấp.
File được validation phải có loại MIME tương ứng với một trong các extension đã được liệt kê.
'photo' => 'mimes:jpeg,bmp,png'
Mặc dù bạn chỉ cần định nghĩa extension của file, nhưng thực ra quy tắc này sẽ validate loại MIME của file bằng cách đọc nội dung của file đó và đoán loại MIME của nó.
Một danh sách đầy đủ các loại MIME và các extension tương ứng của chúng có thể được tìm thấy tại vị trí sau: https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
Field được validation phải có value tối thiểu. Chuỗi, số, mảng và file sẽ được so sánh theo cùng một quy tắc với quy tắc size
.
Field được validation không được chứa trong một danh sách giá trị đã cho. Phương thức Rule::notIn
có thể được sử dụng để dễ dàng xây dựng quy tắc:
use Illuminate\Validation\Rule;
Validator::make($data, [
'toppings' => [
'required',
Rule::notIn(['sprinkles', 'cherries']),
],
]);
Field được validation phải không được khớp với biểu thức chính quy đã cho.
Note: Khi sử dụng mẫu regex
hoặc not_regex
, có thể cần phải khai báo các quy tắc trong một mảng thay vì sử dụng các dấu "|" để phân cách, đặc biệt nếu biểu thức chính quy của bạn chứa ký tự đó.
Field được validation có thể là null
. Điều này đặc biệt hữu ích khi validation loại dữ liệu nguyên thủy chẳng hạn như chuỗi hoặc số nguyên có thể chứa giá trị null
.
Field được validation phải là numeric.
Field được validation phải có tồn tại trong dữ liệu input nhưng có thể trống.
Field được validation phải phù hợp với biểu thức chính quy định.
Note: Khi sử dụng mẫu regex
hoặc not_regex
, có thể cần phải khai báo các quy tắc trong một mảng thay vì sử dụng các dấu "|" để phân cách, đặc biệt nếu biểu thức chính quy của bạn chứa ký tự đó.
Field được validation phải có tồn tại trong dữ liệu input và không được trống. Một field được coi là "trống" nếu một trong các điều kiện sau là đúng:
null
.Countable
của object là trống.Field được validation phải có tồn tại và không được trống nếu trường anotherfield bằng với giá trị value.
Field được validation phải có tồn tại và không được trống khi trường anotherfield không bằng với giá trị value.
Field được validation phải có tồn tại và không được trống chỉ khi một trong các field khác được khai báo có tồn tại.
Field được validation phải có tồn tại và không được trống chỉ khi tất cả các field khác được khai báo đều có tồn tại.
Field được validation phải có tồn tại và không được trống chỉ khi một trong các field khác được khai báo không tồn tại.
Field được validation phải có tồn tại và không được trống chỉ khi tất cả các field khác được khai báo đều không tồn tại.
field đã cho phải match với field được validation.
Field được validation phải có kích thước khớp với value đã cho. Đối với dữ liệu chuỗi, value tương ứng với số lượng ký tự. Đối với dữ liệu số, value tương ứng với một giá trị số nguyên đã cho. Đối với một mảng, size tương ứng với count
của mảng. Đối với file, size tương ứng với kích thước file tính bằng kilobyte.
Field được validation phải là một chuỗi. Nếu bạn muốn cho phép field được null
, thì bạn nên gán quy tắc nullable
cho field.
Field được validation phải là một định danh múi giờ hợp lệ theo hàm PHP timezone_identifiers_list
.
Field được validation phải là duy nhất trong một bảng cơ sở dữ liệu. Nếu tùy chọn column
không được khai báo, chính tên field đó sẽ được sử dụng làm tên cột để so sánh.
Khai báo tên cột
'email' => 'unique:users,email_address'
Khai báo database connection
Đôi khi, bạn có thể cần cài đặt một custom connection cho các truy vấn cơ sở dữ liệu được tạo bởi Validator. Như đã thấy ở trên, việc đặt unique:users
làm quy tắc validate sẽ sử dụng kết nối cơ sở dữ liệu mặc định để truy vấn cơ sở dữ liệu. Để ghi đè lên điều này, bạn cần khai báo thêm thông tin kết nối và tên bảng bằng cú pháp "chấm":
'email' => 'unique:connection.users,email_address'
Bỏ qua một ID nhất định:
Đôi khi, bạn có thể muốn bỏ qua một ID nhất định trong khi kiểm tra unique. Ví dụ: hãy xem thử màn hình "update profile" bao gồm tên người dùng, địa chỉ email và vị trí. Tất nhiên, bạn sẽ muốn kiểm tra rằng địa chỉ email có là unique hay không. Tuy nhiên, nếu người dùng chỉ thay đổi field tên chứ không phải field e-mail, bạn không thể tạo ra lỗi validate vì người dùng đã là chủ sở hữu của địa chỉ email đó.
Để hướng dẫn validator bỏ qua ID của người dùng, chúng ta sẽ sử dụng class Rule
để dễ dàng khai báo quy tắc. Trong ví dụ này, chúng ta cũng sẽ khai báo các quy tắc validation là một mảng thay vì sử dụng ký tự |
để phân chia các quy tắc:
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);
Bạn có thể chỉ định tên cột được validation bằng cách sử dụng tham số thứ hai của phương thức unique
. Nếu không có tham số đó, tên field cần validation sẽ được sử dụng làm tên cột:
'email' => Rule::unique('users', 'email_address')
Nếu bảng của bạn sử dụng tên cột khóa chính khác với id
, bạn có thể chỉ định tên của cột khi gọi phương thức ignore
:
'email' => Rule::unique('users')->ignore($user->id, 'user_id')
Thêm điều kiện where:
Bạn cũng có thể khai báo thêm các điều kiện truy vấn bằng cách sử dụng câu lệnh truy vấn dùng phương thức where
. Ví dụ: hãy thêm một điều kiện là account_id
phải là 1
:
'email' => Rule::unique('users')->where(function ($query) {
return $query->where('account_id', 1);
})
Field được validation phải là một URL hợp lệ.
Trong một số trường hợp, bạn có thể muốn chạy kiểm tra validation đối với một field chỉ khi field đó có trong mảng input. Để nhanh chóng thực hiện điều này, hãy thêm quy tắc sometimes
vào danh sách quy tắc của bạn:
$v = Validator::make($data, [
'email' => 'sometimes|required|email',
]);
Trong ví dụ trên, field email
sẽ chỉ được validate nếu nó có trong mảng $data
.
{tip} Nếu bạn đang validate một field luôn luôn tồn tại nhưng có thể trống, hãy xem ghi chú này trên các field tùy chọn
Thỉnh thoảng bạn có thể muốn thêm các quy tắc validation dựa trên logic điều kiện phức tạp hơn. Ví dụ: bạn muốn bắt buộc nhập một field nếu một field khác có giá trị lớn hơn 100. Hoặc, bạn có thể cần hai field có giá trị mặc định, khi một field khác có tồn tại. Thêm các quy tắc validation này không phải là một điều khó. Đầu tiên, tạo một instance Validator
với static rules không bao giờ thay đổi:
$v = Validator::make($data, [
'email' => 'required|email',
'games' => 'required|numeric',
]);
Giả sử application web của chúng ta là dành cho người sưu tầm trò chơi. Nếu một nhà sưu tập trò chơi đăng ký với application của chúng ta và họ sở hữu hơn 100 trò chơi, chúng ta muốn họ giải thích lý do tại sao họ sở hữu nhiều trò chơi như vậy. Ví dụ, có thể họ điều hành một cửa hàng bán lại trò chơi, hoặc có thể họ chỉ thích thu thập. Để có thêm điều kiện cho các yêu cầu này, chúng ta có thể sử dụng phương thức sometimes
trên instance Validator
.
$v->sometimes('reason', 'required|max:500', function ($input) {
return $input->games >= 100;
});
Tham số đầu tiên được truyền cho phương thức sometimes
là tên của field mà chúng ta đang validate. Tham số thứ hai là các quy tắc mà chúng ta muốn thêm. Và nếu Closure
được truyền làm tham số thứ ba trả về true
, thì quy tắc mới được valdiate. Phương thức này làm cho nó dễ dàng để xây dựng các validate có điều kiện phức tạp. Bạn thậm chí có thể thêm các validate có điều kiện cho một số field cùng một lúc:
$v->sometimes(['reason', 'cost'], 'required', function ($input) {
return $input->games >= 100;
});
{tip} Tham số
$input
được truyền choClosure
của bạn sẽ là một instance củaIlluminate\Support\Fluent
và có thể được sử dụng để truy cập vào field hoặc input đầu vào của bạn.
Validate một mảng được dựa trên các field từ một form input không phải là một vấn đề khó khăn. Bạn có thể sử dụng "ký hiệu chấm" để validate các thuộc tính có trong một mảng. Ví dụ: nếu request HTTP chứa một field photos[profile]
, bạn có thể validate nó như sau:
$validator = Validator::make($request->all(), [
'photos.profile' => 'required|image',
]);
Bạn cũng có thể validate từng phần tử trong một mảng. Ví dụ: để validate rằng mỗi e-mail có trong mảng input field đã cho là duy nhất, bạn có thể làm như sau:
$validator = Validator::make($request->all(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);
Tương tự, bạn có thể sử dụng ký tự *
khi định nghĩa các thông báo validation trong các file language của bạn, giúp dễ dàng sử dụng một thông báo validation duy nhất cho mảng dựa trên các field:
'custom' => [
'person.*.email' => [
'unique' => 'Each person must have a unique e-mail address',
]
],
Laravel cung cấp một loạt các quy tắc validation hữu ích; tuy nhiên, bạn có thể muốn khai báo thêm một số quy tắc của riêng bạn. Một phương thức đăng ký custom validation rule là sử dụng các đối tượng rule. Để tạo một đối tượng rule mới, bạn có thể sử dụng lệnh Artisan make:rule
. Hãy sử dụng lệnh này để tạo rule xác minh chuỗi là chữ hoa. Laravel sẽ tạo rule mới trong thư mục app/Rules
:
php artisan make:rule Uppercase
Khi rule đã được tạo, chúng ta đã sẵn sàng xác định hành vi của nó. Một đối tượng rule sẽ chứa hai phương thức: passes
và message
. Phương thức passes
nhận vào giá trị và tên thuộc tính và sẽ trả về true
hoặc false
tùy thuộc vào giá trị thuộc tính có hợp lệ hay không. Còn phương thức message
sẽ trả về một thông báo lỗi validation, nó sẽ được sử dụng khi validation thất bại:
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class Uppercase implements Rule
{
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
return strtoupper($value) === $value;
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return 'The :attribute must be uppercase.';
}
}
Tất nhiên, bạn có thể gọi helper trans
từ phương thức message
nếu bạn muốn trả về một thông báo lỗi từ các file language của bạn:
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return trans('validation.uppercase');
}
Khi rule đã được định nghĩa xong, bạn có thể gán nó vào một validator bằng cách truyền một instance của đối tượng rule này cùng với các quy tắc validation khác của bạn:
use App\Rules\Uppercase;
$request->validate([
'name' => ['required', 'string', new Uppercase],
]);
Nếu bạn cần chức năng của một rule tùy chỉnh trong đúng một lần trong toàn bộ ứng dụng của bạn, bạn có thể sử dụng Closure thay vì một đối tượng rule. Closure nhận vào tên của thuộc tính, giá trị của thuộc tính đó và một callback $fail
sẽ được gọi nếu quá trình validation không thành công:
$validator = Validator::make($request->all(), [
'title' => [
'required',
'max:255',
function($attribute, $value, $fail) {
if ($value === 'foo') {
return $fail($attribute.' is invalid.');
}
},
],
]);
Một cách khác để đăng ký một tùy biến rule validation là sử dụng phương thức extend
trên facade Validator
. Hãy sử dụng phương thức này trong một service provider để đăng ký một tùy biến rule validation:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Validator::extend('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
}
Một tuỳ biến validator Closure sẽ nhận vào bốn tham số: tên của $attribute
đang được validate, $value
của thuộc tính đó, một mảng $parameters
được truyền đến rule và instance Validator
.
Bạn cũng có thể truyền một class và phương thức của nó cho phương thức extend
thay vì một Closure:
Validator::extend('foo', 'FooValidator@validate');
Bạn cũng sẽ cần định nghĩa một thông báo lỗi cho quy tắc tùy biến của bạn. Bạn có thể làm như vậy bằng cách sử dụng một mảng thông báo tùy biến hoặc bằng cách thêm một mục vào trong file language validation. Thông báo này phải được đặt ở vị trí đầu tiên của mảng, không nằm trong mảng custom
, mảng custom
chỉ dành cho các thông báo lỗi của một thuộc tính cụ thể:
"foo" => "Your input was invalid!",
"accepted" => "The :attribute must be accepted.",
// The rest of the validation error messages...
Khi tạo một tùy biến quy tắc validation, đôi khi bạn có thể cần định nghĩa các thông báo lỗi một cách trực tiếp. Bạn có thể làm như vậy bằng cách tạo tùy biến Validator bằng extend
như được mô tả ở trên, và sau đó thực hiện gọi đến phương thức replacer
trên facade Validator
. Bạn có thể làm điều này trong phương thức boot
của một service provider:
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Validator::extend(...);
Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) {
return str_replace(...);
});
}
Mặc định, khi một thuộc tính được validate không có hoặc chứa một giá trị trống như được định nghĩa bởi quy tắc required
, thì các quy tắc validation thông thường, và cả các extension tùy biến đều sẽ được không chạy. Ví dụ: quy tắc unique
sẽ không được chạy cho giá trị null
:
$rules = ['name' => 'unique'];
$input = ['name' => null];
Validator::make($input, $rules)->passes(); // true
Để một quy tắc chạy ngay cả khi một thuộc tính trống, quy tắc đó phải tưởng tượng rằng thuộc tính là bắt buộc. Để tạo một phần extension "ẩn" như vậy, hãy sử dụng phương thức Validator::extendImplicit()
:
Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
{note} Một extension "ẩn" chỉ tưởng tượng rằng thuộc tính đó là bắt buộc. Việc nó thực sự validate một thuộc tính bị thiếu hoặc bị trống hay không là tùy thuộc vào bạn.
entry