Laravel Validation
Laravel’s base controller class use a ValidatesRequests trait
app/Http/routes.php :
Route::get(‘post/create’, ‘PostController@create’);
Route::post(‘post’, ‘PostController@store’);
Controller
<?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...
}
}
// 直接在 store 方法中,使用 base controller 中的 validatesRequests trait
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
}
只需給 validate 方法,傳送 HTTP request 與需要驗證規(guī)則即可。
注意,如果驗證失敗,自動生成默認的提示。驗證通過,控制器就會自動往下執(zhí)行。
第一個驗證規(guī)則失敗,就停止繼續(xù)往下驗證,對該屬性適應 bail 規(guī)則:
$this->validate($request,[
‘title’ => ‘bail | required | unique:posts|max:255’,
‘body’ => ‘required’
]);
上面的代碼執(zhí)行時,如果 title 在 required 規(guī)則驗證沒通過,那么 unique 規(guī)則將不再被驗證。
驗證規(guī)則會被按照指定的順序來校驗。
對嵌套屬性使用驗證規(guī)則補充說明
如果 HTTP request 包含有嵌套參數(shù),你可以再驗證規(guī)則中使用 “.” 語法來指定需要校驗的參數(shù),如:
$this->validate($request, [
‘title’ => ‘required|unique:post|max:255’,
‘author.name’ => ‘required’,
‘author.description’ => ‘required’,
]);
展示驗證后生成的錯誤提示
如前面提及到的,如果參數(shù)校驗不通過, Laravel 會自動重定向到來源 URL。另外,所有的驗證錯誤就會被自動存入到 session 中。
不需要在 GET 路由中將錯誤信息綁定,Laravel 會自己檢測 session,如果有錯誤就自動綁定到視圖中。
$errors 變量是 Illuminate\Support\MessageBag 的實例。
在這個例子中,驗證不通過,用戶將會被重定向到控制器的 create 方法。我們就可以在視圖中展示錯誤。
<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
自定義錯誤消息提醒格式
自定義驗證不通過的錯誤消息,可以通過在基礎控制器(base controller)重寫 formatValidationErrors。
必須要先在文件頂部,引入 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 請求與參數(shù)驗證
上面例子,是針對使用表單(form)來傳送數(shù)據(jù)給應用,大部分應用使用的是 AJAX 請求。
在一個 AJAX 請求中,使用 validate 方法,Laravel 將不會生成重定向響應。相反,Laravel 會生成一個包含驗證錯誤提示的 JSON 響應。該響應會以 422 HTTP 狀態(tài)碼來發(fā)送回去給客戶端。
校驗輸入字段的數(shù)組為數(shù)組格式
驗證在每一個數(shù)組中的輸入字段是唯一的,只需要
$validator = Validator::make($request->all(), [
'person..email' => 'email|unique:users',
'person..first_name' => 'required_with:person.*.last_name',
]);
同樣,在文件中,當你指定驗證提示時,可以使用 * 字符。
'custom' => [
'person.*.email' => [
'unique' => 'Each person must have a unique e-mail address',
]
],
自己創(chuàng)建驗證器
不想要使用 ValidatesRequests trait’s validate 方法,你可以通過使用 Validator facade 來創(chuàng)建一個 validator 實例。make 方法將會生成一個新的驗證器實例。
<?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...
}
}
make 方法,第一參數(shù)是需要校驗的數(shù)據(jù),第二個參數(shù)是對數(shù)據(jù)進行校驗的規(guī)則。
驗證失敗之后,可以使用 withErrors 方法來將錯誤提示存入會話中。同時,$errors 變量可以再跳轉后,視圖中使用。
withErrors 方法接收一個 validator, 一個 MessageBag,或一個 PHP 數(shù)組。
命名錯誤提示
單個頁面有多個表單,你就會想要對錯誤提示命名,這樣你可以指定接收處理某個指定表單的錯誤信息。
只要傳送一個名字作為 withErrors 的第二個參數(shù)即可。
return redirect(‘register’)->withErrors($validator, ‘login’);
視圖中通過 $errors 變量,來使用 MessageBag 實例:
{{ $errors->login->first(‘email’) }}
驗證后提供的回調處理
validator 允許你指定回調函數(shù),在驗證完成之后就執(zhí)行。這可以使你更容易進行深入的校驗,甚至可以添加更多的錯誤提示。
只需要使用 validator 實例的 after 方法即可。
$validator = Validator::make(...);
$validator->after(function($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
if ($validator->fails()) {
//
}
表單請求驗證
為了應對更加復雜的驗證場景,或許你會想要創(chuàng)建一個“ form request”。表單請求就是,自定義包含有驗證邏輯的請求類。
使用 make:request Artisan 命令行命令 make:request,即可創(chuàng)建一個表單請求類:
php make make:request StoreBlogPostRequest
生成的類放置在 app/Http/Requests 目錄。讓我們添加幾個驗證規(guī)則到 rules 方法中:
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
要怎么樣才能讓驗證規(guī)則執(zhí)行呢?所有你需要的就是,在對應的控制器方法中指定 request (type-hint the request on your controller method)。在控制器方法被調用前,輸入的表單請求會先被驗證,這就意味著你不需要將控制器代碼與數(shù)據(jù)校驗代碼混在一起了。
public function store(StoreBlogPostRequest $request)
{
// The incoming request is valid...
}
驗證失敗,會有重定向響應,使用用戶返回到來源 URL。錯誤提示會被保存到 session,可以直接在視圖中進行使用展示。
如果請求是 AJAX, 返回 JSON 格式的驗證錯誤提示,響應的HTTP狀態(tài)碼為 422 。
表單請求授權
表單請求類中,有 authorise 方法。在這個方法里面,你可以判斷授權用戶是否有權限去更新一個指定的資源。
如:一名用戶想要更新一篇文章的評論,那需要檢查他們是否就是該評論的所有者。
代碼:
public function authorize()
{
$commentId = $this->route('comment');
return Comment::where('id', $commentId)
->where('user_id', Auth::id())->exists();
}
通過使用 route 方法來訪問在路由中定義的 URI 參數(shù),例如:{comment} 參數(shù)定義如下:
Route::post(‘comment/{comment}’);
如果 authorise 方法返回 false,狀態(tài)碼為 403 的響應會自動返回,控制器方法將不會被執(zhí)行。
如果你想要,在應用的其他部分使用用戶授權驗證邏輯,只需要在 authorize 方法中返回 true 就好了。
自定義錯誤提示格式
如果你想要自定義驗證失敗后的錯誤提醒,只需要在 request 基類(App\Http\Requests\Request)中重寫 formatErrors 方法。記得要在類文件頂部引入 Illuminate\Contracts\Validation\Validator。
protected function formatErrors(Validator $validator)
{
return $validator->errors()->all();
}
自定義錯誤提示內容
在表單請求類(app/Http/Requests/LightPostRequest.php)中,重寫 message 方法。該方法必須要返回一個屬性/規(guī)則對,與對應的錯誤的消息。
public function messages()
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
使用錯誤提示信息
通過調用 Validator 實例的 errors 方法,你就可以使用 Illuminate\Support\MessageBag 實例,該實例提供一系列的便捷方法來操作錯誤提示信息。
使用一個字段的第一條錯誤信息
提取一個指定字段的第一條錯誤信息,使用 first 方法“
$message = $validator->error();
echo $message->first(‘email’);
提取一個字段的所有錯誤信息
$message->get(“email”);
foreach ($messages->get('email') as $message) {
//
}
提取所有字段的錯誤信息
$message->all();
foreach ($messages->all() as $message) {
//
}
判斷某個字段時候存在錯誤信息
if ($messages->has('email')) {
//
}
通過一個格式來提取錯誤提示
echo $message->first(‘email’, ‘<p>:message</p>’);
通過一個格式提取所有錯誤提示
foreach($message->all(‘<li>:message</li>’) as $message) {
}