1、簡介
Laravel 提供了多種方法來驗(yàn)證應(yīng)用輸入數(shù)據(jù)。默認(rèn)情況下,Laravel 的控制器基類使用ValidatesRequests
trait,該trait提供了便利的方法通過各種功能強(qiáng)大的驗(yàn)證規(guī)則來驗(yàn)證輸入的 HTTP 請求。
2、快速入門
要掌握 Laravel 強(qiáng)大的驗(yàn)證特性,讓我們先看一個完整的驗(yàn)證表單并返回錯誤信息給用戶的例子。
定義路由
首先,我們假定在 routes/web.php 文件中包含如下路由:
// 顯示創(chuàng)建博客文章表單...
Route::get('post/create', 'PostController@create');
// 存儲新的博客文章...
Route::post('post', 'PostController@store');
當(dāng)然,GET 路由為用戶顯示了一個創(chuàng)建新的博客文章的表單,POST 路由將新的博客文章存儲到數(shù)據(jù)庫。
創(chuàng)建控制器
接下來,讓我們看一個處理這些路由的簡單控制器示例。我們先將 store 方法留空:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
/**
* 顯示創(chuàng)建新的博客文章的表單
*
* @return Response
*/
public function create()
{
return view('post.create');
}
/**
* 存儲新的博客文章
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// 驗(yàn)證并存儲博客文章...
}
}
編寫驗(yàn)證邏輯
現(xiàn)在我們準(zhǔn)備用驗(yàn)證新博客文章輸入的邏輯填充 store 方法。如果你檢查應(yīng)用的控制器基類(App\Http\Controllers\Controller),你會發(fā)現(xiàn)該類使用了ValidatesRequests trait,這個trait 在所有控制器中提供了一個便利的 validate 方法。
validate 方法接收一個 HTTP 請求輸入和一系列驗(yàn)證規(guī)則,如果驗(yàn)證規(guī)則通過,代碼將會繼續(xù)往下執(zhí)行;不過,如果驗(yàn)證失敗,將會拋出一個異常,相應(yīng)的錯誤響應(yīng)也會自動發(fā)送給用戶。在這個傳統(tǒng)的 HTTP 請求 案例中,將會生成一個重定向響應(yīng),如果是 AJAX 請求則會返回一個 JSON 響應(yīng)。
要更好的理解 validate 方法,讓我們回到 store 方法:
/**
* 存儲博客文章
*
* @param Request $request
* @return Response
*/
public function store(Request $request){
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// 驗(yàn)證通過,存儲到數(shù)據(jù)庫...
}
正如你所看到的,我們只是傳遞輸入的 HTTP 請求和期望的驗(yàn)證規(guī)則到 validate 方法。再強(qiáng)調(diào)一次,如果驗(yàn)證失敗,相應(yīng)的響應(yīng)會自動生成。如果驗(yàn)證通過,控制器將會繼續(xù)正常執(zhí)行。
首次驗(yàn)證失敗后中止后續(xù)規(guī)則驗(yàn)證
有時候你可能想要在首次驗(yàn)證失敗后停止檢查該屬性的其它驗(yàn)證規(guī)則,要實(shí)現(xiàn)這個功能,可以在屬性中分配 bail 規(guī)則:
$this->validate($request, [
'title' => 'bail|required|unique:posts|max:255',
'body' => 'required',]
);
在這個例子中,如果 title 屬性上的 required 規(guī)則驗(yàn)證失敗,則不會檢查unique 規(guī)則,規(guī)則會按照分配順序依次進(jìn)行驗(yàn)證。
嵌套屬性注意事項(xiàng)
如果 HTTP 請求中包含“嵌套”參數(shù),可以使用“.”在驗(yàn)證規(guī)則中指定它們:
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);
顯示驗(yàn)證錯誤信息
那么,如果請求輸入?yún)?shù)沒有通過給定驗(yàn)證規(guī)則怎么辦?正如前面所提到的,Laravel 將會自動將用戶重定向回上一個位置。此外,所有驗(yàn)證錯誤信息會自動 一次性存放到 Session。
注意我們并沒有在 GET 路由中明確綁定錯誤信息到視圖。這是因?yàn)?Laravel 總是從 Session 數(shù)據(jù)中檢查錯誤信息,而且如果有的話會自動將其綁定到視圖。所以,值得注意的是每次請求的所有視圖中總是存在一個$errors 變量,從而允許你在視圖中方便而又安全地使用。$errors 變量是一個Illuminate\Support\MessageBag 實(shí)例。
注:
$errors變量會通過web中間件組中的Illuminate\View\Middleware\ShareErrorsFromSession中間件綁定到視圖,如果使用了該中間件,那么$errors變量在視圖中總是有效,從而方便你隨時使用。
所以,在我們的例子中,驗(yàn)證失敗的話用戶將會被重定向到控制器的 create方法,從而允許我們在視圖中顯示錯誤信息:
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
@if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Create Post Form -->
可選字段注意事項(xiàng)
默認(rèn)情況下,Laravel自帶了 TrimStrings 和 ConvertEmptyStringsToNull 中間件,這兩個中間件位于App\Http\Kernel 類 的全局中間件堆棧中,因?yàn)檫@個原因,你需要經(jīng)常將“可選”的請求字段標(biāo)記為 nullable ,如果你不想讓驗(yàn)證器將 null 判定為無效的話。例如:
$this->validate(
$request,
[
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
]
);
在這個例子中,我們指定 publish_at 字段可以為 null 或者有效的日期格式。如果 nullable
沒有被添加到驗(yàn)證規(guī)則,驗(yàn)證器會將 null 判定為無效日期。
自定義錯誤格式
如果你想要自定義保存在 Session 中的驗(yàn)證錯誤信息的格式,需要在控制器基類中重寫formatValidationErrors 方法(不要忘了在該控制器類的頂部導(dǎo)入 Illuminate\Contracts\Validation\Validator類):
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
abstract class Controller extends BaseController{
use DispatchesJobs, ValidatesRequests;
/**
* {@inheritdoc}
*/
protected function formatValidationErrors(Validator $validator)
{
return $validator->errors()->all();
}
}
AJAX請求&驗(yàn)證
在這個例子中,我們使用傳統(tǒng)的表單來發(fā)送數(shù)據(jù)到應(yīng)用。然而,很多應(yīng)用使用 AJAX 請求。在 AJAX 請求中使用 validate 方法時,Laravel 不會生成重定向響應(yīng)。取而代之的,Laravel 生成一個包含驗(yàn)證錯誤信息的 JSON 響應(yīng)。該 JSON 響應(yīng)會帶上一個 HTTP 狀態(tài)碼 422。
3、表單請求驗(yàn)證
創(chuàng)建表單請求
對于更復(fù)雜的驗(yàn)證場景,你可能想要創(chuàng)建一個“表單請求”。表單請求是包含驗(yàn)證邏輯的自定義請求類,要創(chuàng)建表單驗(yàn)證類,可以使用Artisan 命令 make:request:
php artisan make:request StoreBlogPost
生成的類位于 app/Http/Requests 目錄下,如果該目錄不存在,運(yùn)行 make:request 命令時會替我們生成。接下來我們添加少許驗(yàn)證規(guī)則到 rules 方法:
/**
* 獲取應(yīng)用到請求的驗(yàn)證規(guī)則
*
* @return array
*/
public function rules(){
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
那么,驗(yàn)證規(guī)則如何生效呢?你所要做的就是在控制器方法中類型提示該請求。表單輸入請求會在控制器方法被調(diào)用之前被驗(yàn)證,這就是說你不需要將控制器和驗(yàn)證邏輯雜糅在一起:
/**
* 存儲輸入的博客文章
*
* @param StoreBlogPostRequest $request
* @return Response
*/
public function store(StoreBlogPost $request){
// The incoming request is valid...
}
如果驗(yàn)證失敗,重定向響應(yīng)會被生成并將用戶退回上一個位置,錯誤信息也會被存儲到一次性 Session 以便在視圖中顯示。如果是 AJAX 請求,帶 422 狀態(tài)碼的 HTTP 響應(yīng)將會返回給用戶,該響應(yīng)數(shù)據(jù)中還包含了 JSON 格式的驗(yàn)證錯誤信息。
添加驗(yàn)證后鉤子到表單請求
如果你想要添加“驗(yàn)證后”鉤子到表單請求,可以使用 withValidator 方法。該方法接收完整的構(gòu)造驗(yàn)證器,從而允許你在驗(yàn)證規(guī)則執(zhí)行前調(diào)用任何驗(yàn)證器方法:
/**
* 配置驗(yàn)證器實(shí)例.
*
* @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!');
}
});
}
授權(quán) 表單請求
表單請求類還包含了一個 authorize 方法,你可以檢查認(rèn)證用戶是否有權(quán)限更新指定資源。例如,如果用戶嘗試更新一個博客評論,那么他是否是該評論的所有者呢?舉個例子:
/**
* 判定用戶是否被授權(quán)發(fā)起請求.
*
* @return bool
* @translator laravelacademy.org
*/
public function authorize()
{
$comment = Comment::find($this->route('comment'));
return $comment && $this->user()->can('update', $comment);
}
由于所有請求都繼承自 Laravel 請求基類,我們可以使用user 方法獲取當(dāng)前認(rèn)證用戶,還要注意上面這個例子中對route 方法的調(diào)用。該方法賦予用戶訪問被調(diào)用路由 URI 參數(shù)的權(quán)限,比如下面這個例子中的 {comment} 參數(shù):
Route::post('comment/{comment}');
如果 authorize 方法返回 false,一個包含 403 狀態(tài)碼的 HTTP 響應(yīng)會自動返回而且控制器方法將不會被執(zhí)行。
如果你計劃在應(yīng)用的其他部分包含授權(quán)邏輯,只需在authorize 方法中簡單返回 true 即可:
/**
* 判斷請求用戶是否經(jīng)過認(rèn)證
*
* @return bool
*/
public function authorize(){
return true;
}
自定義錯誤格式
如果你想要自定義驗(yàn)證失敗時存儲到一次性 Session 中驗(yàn)證錯誤信息的格式,重寫請求基類(App\Http\Requests\Request)中的 formatErrors 方法即可。不要忘記在文件頂部導(dǎo)入 Illuminate\Contracts\Validation\Validator 類:
/**
* {@inheritdoc}
*/
protected function formatErrors(Validator $validator){
return $validator->errors()->all();
}
自定義錯誤消息
你可以通過重寫 messages 方法自定義表單請求使用的錯誤消息,該方法應(yīng)該返回屬性/規(guī)則對數(shù)組及其對應(yīng)錯誤消息:
/**
* 獲取被定義驗(yàn)證規(guī)則的錯誤消息.
*
* @return array
* @translator laravelacademy.org
*/
public function messages(){
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
4、 手動創(chuàng)建驗(yàn)證器
如果你不想使用 ValidatesRequests trait提供的validate 方法,可以使用 Validator Facade手動創(chuàng)建一個驗(yàn)證器實(shí)例,該門面上的 make 方法用于生成一個新的驗(yàn)證器實(shí)例:
<?php
namespace App\Http\Controllers;
use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller{
/**
* 存儲新的博客文章
*
* @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();
}
// 存儲博客文章...
}
}
傳遞給 make 方法的第一個參數(shù)是需要驗(yàn)證的數(shù)據(jù),第二個參數(shù)是要應(yīng)用到數(shù)據(jù)上的驗(yàn)證規(guī)則。
檢查請求是夠通過驗(yàn)證后,可以使用 withErrors 方法將錯誤數(shù)據(jù)存放到一次性 Session,使用該方法時,$errors 變量重定向后自動在視圖間共享,從而允許你輕松將其顯示給用戶,withErrors 方法接收一個驗(yàn)證器、或者一個 MessageBag ,又或者一個 PHP 數(shù)組。
自動重定向
如果你想要手動創(chuàng)建一個驗(yàn)證器實(shí)例,但仍然使用ValidatesRequest trait提供的自動重定向,可以調(diào)用已存在驗(yàn)證器上的 validate 方法,如果驗(yàn)證失敗,用戶將會被自動重定向,或者,如果是 AJAX 請求的話,返回 JSON 響應(yīng):
Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validate();
命名錯誤包
如果你在單個頁面上有多個表單,可能需要命名錯誤的 MessageBag,從而允許你為指定表單獲取錯誤信息。只需要傳遞名稱作為第二個參數(shù)給 withErrors 即可:
return redirect('register')
->withErrors($validator, 'login');
然后你就可以從 $errors 變量中訪問命名的 MessageBag 實(shí)例:
{{ $errors->login->first('email') }}
驗(yàn)證鉤子之后
驗(yàn)證器允許你在驗(yàn)證完成后添加回調(diào),這種機(jī)制允許你輕松執(zhí)行更多驗(yàn)證,甚至添加更多錯誤信息到消息集合。使用驗(yàn)證器實(shí)例上的 after 方法即可:
$validator = Validator::make(...);
$validator->after(function($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
if ($validator->fails()) {
//
}
5、處理錯誤信息
調(diào)用 Validator 實(shí)例上的 errors 方法之后,將會獲取一個 Illuminate\Support\MessageBag 實(shí)例,該實(shí)例中包含了多種處理錯誤信息的便利方法。在所有視圖中默認(rèn)有效的 $errors 變量也是一個 MessageBag 實(shí)例。
獲取某字段的第一條錯誤信息
要獲取指定字段的第一條錯誤信息,可以使用 first 方法:
$errors = $validator->errors();
echo $errors->first('email');
獲取指定字段的所有錯誤信息
如果你想要簡單獲取指定字段的所有錯誤信息數(shù)組,使用 get 方法:
foreach ($errors->get('email') as $message) {
//
}
如果是一個數(shù)組表單字段,可以使用 * 獲取所有數(shù)組元素錯誤信息:
foreach ($errors->get('attachments.*') as $message) {
//
}
獲取所有字段的所有錯誤信息
要獲取所有字段的所有錯誤信息,可以使用 all 方法:
foreach ($errors->all() as $message) {
//
}
判斷消息中是否存在某字段的錯誤信息
has 方法可用于判斷錯誤信息中是否包含給定字段:
``php
if ($errors->has(’email’)) {
//
}
**獲取指定格式的錯誤信息**
```php
echo $errors->first(’email’, ‘
:message
‘);
獲取指定格式的所有錯誤信息
foreach ($errors->all('<li>:message</li>') as $message) {
//
}
自定義錯誤信息
如果需要的話,你可以使用自定義錯誤信息替代默認(rèn)的,有多種方法來指定自定義信息。首先,你可以傳遞自定義信息作為第三個參數(shù)給 Validator::make 方法:
$messages = [
'required' => 'The :attribute field is required.',
];
$validator = Validator::make($input, $rules, $messages);
在本例中,:attribute 占位符將會被驗(yàn)證時實(shí)際的字段名替換,你還可以在驗(yàn)證消息中使用其他占位符,例如:
$messages = [
'same' => 'The :attribute and :other must match.',
'size' => 'The :attribute must be exactly :size.',
'between' => 'The :attribute must be between :min - :max.',
'in' => 'The :attribute must be one of the following types: :values',
];
為給定屬性指定自定義信息
有時候你可能只想為特定字段指定自定義錯誤信息,可以通過“.”來實(shí)現(xiàn),首先指定屬性名,然后是規(guī)則:
$messages = [
'email.required' => 'We need to know your e-mail address!',
];
在語言文件中指定自定義消息
在很多案例中,你可能想要在語言文件中指定自定義消息而不是將它們直接傳遞給 Validator。要實(shí)現(xiàn)這個,添加消息到 resources/lang/xx/validation.php 語言文件的custom 數(shù)組:
'custom' => [
'email' => [
'required' => 'We need to know your e-mail address!',
],
],
在語言文件中指定自定義屬性
如果你想要將驗(yàn)證消息的 :attribute 部分替換成自定義屬性名稱,可以在語言文件 resources/lang/xx/validation.php 的 attributes 數(shù)組中指定自定義名稱:
'attributes' => [
'email' => 'email address',
],
6、驗(yàn)證規(guī)則大全
下面是有效規(guī)則及其函數(shù)列表:
- Accepted
- Active URL
- After (Date)
- After Or Equal(Date)
- Alpha
- Alpha Dash
- Alpha Numeric
- Array
- Before (Date)
- Before Or Equal(Date)
- Between
- Boolean
- Confirmed
- Date
- Date Format
- Different
- Digits
- Digits Between
- Dimensions(圖片文件)
- Distinct
- Exists (Database)
- File
- Filled
- Image (File)
- In
- In Array
- Integer
- IP Address
- JSON
- Max
- MIME Types (File)
- MIME Type By File Extension
- Min
- Nullable
- Not In
- 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
accepted
驗(yàn)證字段的值必須是yes、on、1或true,這在“同意服務(wù)協(xié)議”時很有用。
active_url
驗(yàn)證字段必須是基于 PHP 函數(shù) dns_get_record 的,有A 或 AAAA 記錄的值。
after:date
驗(yàn)證字段必須是給定日期之后的一個值,日期將會通過 PHP 函數(shù) strtotime
傳遞:
'start_date' => 'required|date|after:tomorrow'
你可以指定另外一個與日期進(jìn)行比較的字段,而不是傳遞一個日期字符串給 strtotime
執(zhí)行:
'finish_date' => 'required|date|after:start_date'
after_or_equal:date
驗(yàn)證字段必須是大于等于給定日期的值,更多信息,請參考after:date
規(guī)則。
alpha
驗(yàn)證字段必須是字母。
alpha_dash
驗(yàn)證字段可以包含字母和數(shù)字,以及破折號和下劃線。
alpha_num
驗(yàn)證字段必須是字母或數(shù)字。
array
驗(yàn)證字段必須是 PHP 數(shù)組。
before:date
驗(yàn)證字段必須是指定日期之前的一個數(shù)值,日期將會傳遞給PHP strtotime
函數(shù)。
before_or_equal:date
驗(yàn)證字段必須小于等于給定日期。日期將會傳遞給 PHP 的 strtotime
函數(shù)。
between:min,max
驗(yàn)證字段大小在給定的最小值和最大值之間,字符串、數(shù)值和文件都可以像使用 size
規(guī)則一樣使用該規(guī)則。
boolean
驗(yàn)證字段必須可以被轉(zhuǎn)化為布爾值,接收true, false, 1 , 0, "1" 和 "0" 等輸入。
confirmed
驗(yàn)證字段必須有一個匹配字段 foo_confirmation,例如,如果驗(yàn)證字段是password,必須輸入一個與之匹配的password_confirmation 字段。
date
驗(yàn)證字段必須是一個基于 PHP strtotime函數(shù)的有效日期
date_format:format
驗(yàn)證字段必須匹配指定格式,可以使用 PHP 函數(shù)date 或 date_format 驗(yàn)證該字段。
different:field
驗(yàn)證字段必須是一個和指定字段不同的值。
digits:value
驗(yàn)證字段必須是數(shù)字且長度為value指定的值。
digits_between:min,max
驗(yàn)證字段數(shù)值長度必須介于最小值和最大值之間。
dimensions
驗(yàn)證的圖片尺寸必須滿足該規(guī)定參數(shù)指定的約束條件:
'avatar' => 'dimensions:min_width=100,min_height=200'
有效的約束條件包括:min_width, max_width, min_height, max_height, width, height, ratio。ratio 約束應(yīng)該是寬度/高度,這可以通過表達(dá)式3/2或浮點(diǎn)數(shù)1.5 來表示:
'avatar' => 'dimensions:ratio=3/2'
由于該規(guī)則要求多個參數(shù),可以使用 Rule::dimensions方法來構(gòu)造該規(guī)則:
use Illuminate\Validation\Rule;Validator::make($data, [ 'avatar' => [ 'required', Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2), ],]);
distinct
處理數(shù)組時,驗(yàn)證字段不能包含重復(fù)值:
'foo.*.id' => 'distinct'
email
驗(yàn)證字段必須是格式化的電子郵件地址
exists:table,column
驗(yàn)證字段必須存在于指定數(shù)據(jù)表基本使用:
'state' => 'exists:states'
指定自定義列名:
'state' => 'exists:states,abbreviation'
還可以添加更多查詢條件到where 查詢子句:
'email' => 'exists:staff,email,account_id,1'
這些條件還可以包含!:
'email' => 'exists:staff,email,role,!admin'
還可以傳遞 NULL 或 NOT NULL 到 where 子句:
'email' => 'exists:staff,email,deleted_at,NULL'
'email' => 'exists:staff,email,deleted_at,NOT_NULL'
有時,你可能需要為 exists 查詢指定要使用的數(shù)據(jù)庫連接,這可以通過在表名前通過.前置數(shù)據(jù)庫連接來實(shí)現(xiàn):
'email' => 'exists:connection.staff,email'
如果你想要自定義驗(yàn)證規(guī)則執(zhí)行的查詢,可以使用 Rule 類來定義規(guī)則。在這個例子中,我們還以數(shù)組形式指定了驗(yàn)證規(guī)則,而不是使用 | 字符來限定它們:
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::exists('staff')->where(function ($query) {
$query->where('account_id', 1);
}),
],
]);
file
驗(yàn)證字段必須是上傳成功的文件。
filled
驗(yàn)證字段如果存在則不能為空。
image
驗(yàn)證文件必須是圖片(jpeg、png、bmp、gif或者svg)
in:foo,bar…
驗(yàn)證字段值必須在給定的列表中,由于該規(guī)則經(jīng)常需要我們對數(shù)組進(jìn)行implode,可以使用Rule::in 來構(gòu)造這個規(guī)則:
use Illuminate\Validation\Rule;
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
]);
in_array:另一個字段
驗(yàn)證字段必須在另一個字段值中存在。
integer
驗(yàn)證字段必須是整型。
ip
驗(yàn)證字段必須是IP地址。
ipv4
驗(yàn)證字段必須是IPv4地址。
ipv6
驗(yàn)證字段必須是IPv6地址。
json
驗(yàn)證字段必須是有效的JSON字符串
max:value
驗(yàn)證字段必須小于等于最大值,和字符串、數(shù)值、文件字段的size 規(guī)則一樣使用
mimetypes:text/plain…
驗(yàn)證文件必須匹配給定的 MIME文件類型之一:
'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'
為了判斷上傳文件的 MIME 類型,框架將會讀取文件內(nèi)容來猜測 MIME 類型,這可能會和客戶端 MIME 類型不同。
mimes:foo,bar,…
驗(yàn)證文件的 MIME 類型必須是該規(guī)則列出的 擴(kuò)展 類型中的一個 MIME規(guī)則的基本使用:
'photo' => 'mimes:jpeg,bmp,png'
盡管你只需要指定擴(kuò)展,該規(guī)則實(shí)際上驗(yàn)證的是通過讀取文件內(nèi)容獲取到的文件MIME類型。
完整的MIME類型列表及其相應(yīng)的擴(kuò)展可以在這里找到:http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
min:value
驗(yàn)證字段必須大于等于最小值,對字符串、數(shù)值、文件字段而言,和size 規(guī)則使用方式一致。
nullable
驗(yàn)證字段可以是null,這在驗(yàn)證一些可以為 null 的原生數(shù)據(jù)如整型或字符串時很有用。
not_in:foo,bar,…
驗(yàn)證字段值不能在給定列表中
numeric
驗(yàn)證字段必須是數(shù)值
present
驗(yàn)證字段必須出現(xiàn)在輸入數(shù)據(jù)中但可以為空。
regex:pattern
驗(yàn)證字段必須匹配給定正則表達(dá)式
注:使用
regex模式時,規(guī)則必須放在數(shù)組中,而不能使用管道分隔符,尤其是正則表達(dá)式中已經(jīng)使用了管道符號時。
required
驗(yàn)證字段值不能為空,以下情況字段值都為空:
- 值為
null - 值是空字符串
- 值是空數(shù)組或者空的
Coutable對象 - 值是上傳文件但路徑為空
required_if:anotherfield,value,…
驗(yàn)證字段在另一個字段等于指定值value時是必須的
required_unless:anotherfield,value,…
除非 anotherfield 字段等于value,否則驗(yàn)證字段不能空
required_with:foo,bar,…
驗(yàn)證字段只有在任一其它指定字段存在的情況才是必須的
required_with_all:foo,bar,…
驗(yàn)證字段只有在所有指定字段存在的情況下才是必須的
required_without:foo,bar,…
驗(yàn)證字段只有當(dāng)任一指定字段不存在的情況下才是必須的
required_without_all:foo,bar,…
驗(yàn)證字段只有當(dāng)所有指定字段不存在的情況下才是必須的
same:field
給定字段和驗(yàn)證字段必須匹配
size:value
驗(yàn)證字段必須有和給定值value相匹配的尺寸,對字符串而言,value是相應(yīng)的字符數(shù)目;對數(shù)值而言,value是給定整型值;對文件而言,value是相應(yīng)的文件字節(jié)數(shù)
string
驗(yàn)證字段必須是字符串,如果允許字段為空,需要分配nullable 規(guī)則到該字段。
timezone
驗(yàn)證字符必須是基于 PHP 函數(shù)timezone_identifiers_list 的有效時區(qū)標(biāo)識
unique:table,column,except,idColumn
驗(yàn)證字段在給定數(shù)據(jù)表上必須是唯一的,如果不指定column 選項(xiàng),字段名將作為默認(rèn)column。
指定自定義列名:
'email' => 'unique:users,email_address'
自定義數(shù)據(jù)庫連接
有時候,你可能需要自定義驗(yàn)證器生成的數(shù)據(jù)庫連接,正如上面所看到的,設(shè)置unique:users 作為驗(yàn)證規(guī)則將會使用默認(rèn)數(shù)據(jù)庫連接來查詢數(shù)據(jù)庫。要覆蓋默認(rèn)連接,在數(shù)據(jù)表名后使用“.”指定連接:
'email' => 'unique:connection.users,email_address'
強(qiáng)制一個唯一規(guī)則來忽略給定ID:
有時候,你可能希望在唯一檢查時忽略給定ID,例如,考慮一個包含用戶名、郵箱地址和位置的”更新屬性“界面,當(dāng)然,你將會驗(yàn)證郵箱地址是唯一的,然而,如果用戶只改變用戶名字段而并沒有改變郵箱字段,你不想要因?yàn)橛脩粢呀?jīng)擁有該郵箱地址而拋出驗(yàn)證錯誤,你只想要在用戶提供的郵箱已經(jīng)被別人使用的情況下才拋出驗(yàn)證錯誤。
要告訴驗(yàn)證器忽略用戶ID,可以使用 Rule 類類定義這個規(guī)則,我們還要以數(shù)組方式指定驗(yàn)證規(guī)則,而不是使用|來界定規(guī)則:
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);
如果你的數(shù)據(jù)表使用主鍵字段不是id,可以在調(diào)用ignore 方法的時候指定字段名稱:
'email' => Rule::unique('users')->ignore($user->id, 'user_id')
添加額外的where子句:
使用where方法自定義查詢的時候還可以指定額外查詢約束,例如,下面我們來添加一個驗(yàn)證account_id為1 的約束:
'email' => Rule::unique('users')->where(function ($query) {
$query->where('account_id', 1);
})
url
驗(yàn)證字段必須是有效的URL。
7、添加條件規(guī)則
存在時驗(yàn)證
在某些場景下,你可能想要只有某個字段存在的情況下進(jìn)行驗(yàn)證檢查,要快速實(shí)現(xiàn)這個,添加 sometimes 規(guī)則到規(guī)則列表:
$v = Validator::make($data, [
'email' => 'sometimes|required|email',
]);
在上例中,email 字段只有存在于 $data 數(shù)組時才會被驗(yàn)證。
復(fù)雜條件驗(yàn)證
有時候你可能想要基于更復(fù)雜的條件邏輯添加驗(yàn)證規(guī)則。例如,你可能想要只有在另一個字段值大于100時才要求一個給定字段是必須的,或者,你可能需要只有當(dāng)另一個字段存在時兩個字段才都有給定值。添加這個驗(yàn)證規(guī)則并不是一件頭疼的事。首先,創(chuàng)建一個永遠(yuǎn)不會改變的靜態(tài)規(guī)則到 Validator 實(shí)例:
$v = Validator::make($data, [
'email' => 'required|email',
'games' => 'required|numeric',
]);
讓我們假定我們的 Web 應(yīng)用服務(wù)于游戲收集者。如果一個游戲收集者注冊了我們的應(yīng)用并擁有超過 100 個游戲,我們想要他們解釋為什么他們會有這么多游戲,例如,也許他們在運(yùn)營一個游戲二手店,又或者他們只是喜歡收集。要添加這種條件,我們可以使用 Validator 實(shí)例上的 sometimes方法:
$v->sometimes('reason', 'required|max:500', function($input) {
return $input->games >= 100;
});
傳遞給 sometimes 方法的第一個參數(shù)是我們需要有條件驗(yàn)證的名稱字段,第二個參數(shù)是我們想要添加的規(guī)則,如果作為第三個參數(shù)的閉包返回true,規(guī)則被添加。該方法讓構(gòu)建復(fù)雜條件驗(yàn)證變得簡單,你甚至可以一次為多個字段添加條件驗(yàn)證:
$v->sometimes(['reason', 'cost'], 'required', function($input) {
return $input->games >= 100;
});
注:傳遞給閉包的
$input參數(shù)是Illuminate\Support\Fluent的一個實(shí)例,可用于訪問輸入和文件。
8、驗(yàn)證數(shù)組輸入
驗(yàn)證表單數(shù)組輸入字段不再是件痛苦的事情,例如,要驗(yàn)證給定數(shù)組輸入中每個 email 是否是唯一的,可以這么做:
$validator = Validator::make($request->all(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);
類似地,在語言文件中你也可以使用*字符指定驗(yàn)證消息,從而可以使用單個消息定義基于數(shù)組字段的驗(yàn)證規(guī)則:
'custom' => [
'person.*.email' => [
'unique' => 'Each person must have a unique e-mail address',
]
],
9、自定義驗(yàn)證規(guī)則
Laravel 提供了多種有用的驗(yàn)證規(guī)則;不過,你可能還是想要指定一些自己的驗(yàn)證規(guī)則。注冊驗(yàn)證規(guī)則的一種方法是使用Validator Facade的 extend 方法。讓我們在服務(wù)提供者中使用這種方法來注冊一個自定義的驗(yàn)證規(guī)則:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
/**
* 啟動應(yīng)用服務(wù)
*
* @return void
*/
public function boot()
{
Validator::extend('foo', function($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
}
/**
* 注冊服務(wù)提供者
*
* @return void
*/
public function register()
{
//
}
}
自定義驗(yàn)證器閉包接收四個參數(shù):要驗(yàn)證的屬性名稱、屬性值、傳遞給規(guī)則的參數(shù)數(shù)組以及Validator
實(shí)例。你還可以傳遞類和方法到 extend 方法而不是閉包:
Validator::extend('foo', 'FooValidator@validate');
定義錯誤信息
你還需要為自定義規(guī)則定義錯誤信息。你可以使用內(nèi)聯(lián)自定義消息數(shù)組或者在驗(yàn)證語言文件中添加條目來實(shí)現(xiàn)這一目的。消息應(yīng)該被放到數(shù)組的第一維,而不是在只用于存放屬性指定錯誤信息的 custom
數(shù)組內(nèi):
"foo" => "Your input was invalid!",
"accepted" => "The :attribute must be accepted.",
// 驗(yàn)證錯誤信息其它部分...
當(dāng)創(chuàng)建一個自定義驗(yàn)證規(guī)則時,你可能有時候需要為錯誤信息定義自定義占位符,可以通過創(chuàng)建自定義驗(yàn)證器然后調(diào)用Validator Facade上的replacer 方法來實(shí)現(xiàn)??梢栽?服務(wù)提供者 的boot 方法中編寫代碼:
/**
* 啟動應(yīng)用服務(wù)
*
* @return void
* @translator laravelacademy.org
*/
public function boot(){
Validator::extend(...);
Validator::replacer('foo', function($message, $attribute, $rule, $parameters) {
return str_replace(...);
});
}
隱式擴(kuò)展
默認(rèn)情況下,被驗(yàn)證的屬性如果沒有提供或者驗(yàn)證規(guī)則為required 而值為空,那么正常的驗(yàn)證規(guī)則,包括自定義擴(kuò)展將不會執(zhí)行。例如 unique規(guī)則將不會檢驗(yàn)null 值:
$rules = ['name' => 'unique'];
$input = ['name' => null];
Validator::make($input, $rules)->passes();
// true
如果要求即使為空時也要驗(yàn)證屬性,則必須要暗示屬性是必須的,要創(chuàng)建一個隱式擴(kuò)展,可以使用Validator::extendImplicit() 方法:
Validator::extendImplicit('foo', function($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
注:一個隱式擴(kuò)展僅僅暗示屬性是必須的,至于它到底是缺失的還是空值這取決于你。