表单验证
基本用法
Laravel 通过 Validator
类让您可以简单、方便的验证数据正确性及查看相应的验证错误信息。
基本验证例子
$validator = Validator::make(
['name' => 'Dayle'],
['name' => 'required|min:5']
);
上文中传递给 make
这个方法的第一个参数用来设定所需要被验证的数据名称,第二个参数设定该数据可被接受的规则。
使用数组来定义规则
多个验证规则可以使用"|"符号分隔,或是单一数组作为单独的元素分隔。
$validator = Validator::make(
['name' => 'Dayle'],
['name' => ['required', 'min:5']]
);
验证多个字段
$validator = Validator::make(
[
'name' => 'Dayle',
'password' => 'lamepassword',
'email' => 'email@example.com'
],
[
'name' => 'required',
'password' => 'required|min:8',
'email' => 'required|email|unique:users'
]
);
当一个 Validator
实例被建立后,fails
(或 passes
) 这两个方法就可以在验证时使用,如下:
if ($validator->fails())
{
// The given data did not pass validation
}
假如验证失败,您可以从验证器中接收错误信息。
$messages = $validator->messages();
您可能不需要错误信息,只想取得无法通过验证的规则,您可以使用 failed
方法:
$failed = $validator->failed();
验证文件
Validator
类提供了一些规则用来验证文件,例如 size
, mimes
等等。当需要验证文件时,您仅需将它们和您其他的数据一同送给验证器即可。
验证后钩子
验证器也允许你在完成验证后增加回调函数。这也允许你可以进行更进一步的验证,甚至在消息集合中增加更多的错误信息。我们在验证器实例中使用 after
方法来作为开始:
$validator = Validator::make(...);
$validator->after(function($validator)
{
if ($this->somethingElseIsInvalid())
{
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
if ($validator->fails())
{
//
}
您可以根据需要为验证器增加任意的 after
回调函数。
控制器验证
当然,如果每一次需要验证的时候都手动的建立并且验证 Validator
实例会非常的麻烦。不用担心,你有其他的选择!Laravel自带的 App\Http\Controllers\Controller
基类使用了一个 ValidatesRequests
的 trait。这个 trait 提供了一个单一的、便捷的方法来验证 HTTP 请求。代码如下:
/**
* Store the incoming blog post.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|unique|max:255',
'body' => 'required',
]);
//
}
如果验证通过了,你的代码会正常继续执行。如果验证失败,那么会抛出一个 Illuminate\Contracts\Validation\ValidationException
异常。这个异常会被自动捕获,然后重定向至用户上一个页面。而错误信息甚至已经存储至 session 中!
如果收到的是一个 AJAX 请求,那么不会生成一个重定向。相反的,一个带有 422 状态码的 HTTP 响应会被返回给浏览器,包含了一个含有错误信息的 JSON 对象。
比如,如下是手动创建验证的等效写法:
/**
* Store the incoming blog post.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$v = Validator::make($request->all(), [
'title' => 'required|unique|max:255',
'body' => 'required',
]);
if ($v->fails())
{
return redirect()->back()->withErrors($v->errors());
}
//
}
自定义闪存后的错误格式
如果你想要自定义验证失败后已经闪存至 session 的错误消息格式,可以通过覆盖基类控制器的 formatValidationErrors
。不要忘记在文件顶部引入 Illuminate\Validation\Validator
类。
/**
* {@inheritdoc}
*/
protected function formatValidationErrors(Validator $validator)
{
return $validator->errors()->all();
}
表单请求验证
如果是更复杂的验证场景,你可能需要创建一个"表单请求"。表单请求是一个自定义的请求类包含了一些验证的逻辑。你可以通过 Artisan 的命令行 make:request
来创建一个表单请求类。
php artisan make:request StoreBlogPostRequest
生成的类会放置在 app/Http/Requests
目录中。 我们在 rules
方法中增加一些验证规则:
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|unique|max:255',
'body' => 'required',
];
}
那么,我们的验证规则是怎么执行的呢?你所要做的只是在控制器方法中加上请求的类型提示:
/**
* Store the incoming blog post.
*
* @param StoreBlogPostRequest $request
* @return Response
*/
public function store(StoreBlogPostRequest $request)
{
// The incoming request is valid...
}
当控制器的方法被调用前,表单请求已经验证了,意味着你不需要在控制器里写任何的验证逻辑。它已经验证完了!
如果验证失败,用户会收到一个重定向请求至上一个页面。而错误信息也已经存储至 session 中方便视图展示。如果收到的是一个 AJAX 请求,一个带有 422 状态码的 HTTP 响应会被返回给浏览器,包含了一个含有错误信息的 JSON 对象。
授权表单请求
表单请求类同样也包含了一个 authorize
方法。通过这个方法,你可以检查认证后的用户是否有权限去更新一个已有的资源。比如,如果一个用户尝试去更新一篇博客的评论,他是否真的发布过这个评论?举个例子:
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$commentId = $this->route('comment');
return Comment::where('id', $commentId)
->where('user_id', Auth::id())->exists();
}
注意上面例子中调用的 route
方法。这个方法允许你获取调用路由中定义的 URI 参数,比如下面例子中的 {comment}
参数:
Route::post('comment/{comment}');
如果 authorize
方法返回 false
, 一个带有 403 状态码的 HTTP 响应会被返回给浏览器,你控制器的方法也不会被执行。
如果你打算在应用的其他地方做一些权限的逻辑,在 authorize
方法中返回 true
即可:
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
自定义闪存后的错误信息格式
如果你想要自定义验证失败后已经闪存至 session 的错误消息格式,可以通过覆盖基类请求类(App\Http\Requests\Request
)的 formatErrors
。不要忘记在文件顶部引入 Illuminate\Validation\Validator
类:
/**
* {@inheritdoc}
*/
protected function formatErrors(Validator $validator)
{
return $validator->errors()->all();
}
使用错误信息
当您调用一个 Validator
实例的 messages
方法后,您会得到一个命名为 MessageBag
的实例,该实例里有许多方便的方法能让您取得相关的错误信息。
查看一个字段的第一个错误信息
echo $messages->first('email');
查看一个字段的所有错误信息
foreach ($messages->get('email') as $message)
{
//
}
查看所有字段的所有错误信息
foreach ($messages->all() as $message)
{
//
}
判断一个字段是否有错误信息
if ($messages->has('email'))
{
//
}
错误信息格式化输出
echo $messages->first('email', '<p>:message</p>');
默认错误信息以 Bootstrap 兼容语法输出。
查看所有错误信息并以格式化输出
foreach ($messages->all('<li>:message</li>') as $message)
{
//
}
错误信息 & 视图
当您开始进行验证数据时,您会需要一个简易的方法去取得错误信息并返回到您的视图中,在 Laravel 中您可以很方便的处理这些操作,您可以通过下面的路由例子来了解:
Route::get('register', function()
{
return View::make('user.register');
});
Route::post('register', function()
{
$rules = [...];
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails())
{
return redirect('register')->withErrors($validator);
}
});
需要记住的是,当验证失败后,我们会使用 withErrors
方法来将 Validator
实例进行重定向。这个方法会将错误信息存入 session 中,这样才能在下个请求中被使用。
然而,我们并不需要特别去将错误信息绑定在我们 GET 路由的视图中。因为 Laravel 会确认在 Session 数据中检查是否有错误信息,并且自动将它们绑定至视图中。所以请注意,$errors
变量存在于所有的视图中,所有的请求里,让您可以直接假设 $errors
变量已被定义且可以安全地使用。$errors
变量是 MessageBag
类的一个实例。
所以,在重定向之后,您可以自然的在视图中使用 $errors
变量:
<?php echo $errors->first('email'); ?>
命名错误清单
假如您在一个页面中有许多的表单,您可能希望为错误命名一个 MessageBag
。 这样能方便您针对特定的表单查看其错误信息, 我们只要简单的在 withErrors
的第二个参数设定名称即可:
return redirect('register')->withErrors($validator, 'login');
接着您可以从一个 $errors
变量中取得已命名的 MessageBag
实例:
<?php echo $errors->login->first('email'); ?>
可用验证规则
以下是现有可用的验证规则清单与他们的函数名称:
- Accepted
- Active URL
- After (Date)
- Alpha
- Alpha Dash
- Alpha Numeric
- Array
- Before (Date)
- Between
- Boolean
- Confirmed
- Date
- Date Format
- Different
- Digits
- Digits Between
- Exists (Database)
- Image (File)
- In
- Integer
- IP Address
- Max
- MIME Types
- Min
- Not In
- Numeric
- Regular Expression
- Required
- Required If
- Required With
- Required With All
- Required Without
- Required Without All
- Same
- Size
- String
- Timezone
- Unique (Database)
- URL
accepted
字段值为 yes, on, 或是 1 时,验证才会通过。这在确认"服务条款"是否同意时很有用。
active_url
字段值通过 PHP 函数 checkdnsrr
来验证是否为一个有效的网址。
after:date
验证字段是否是在指定日期之后。这个日期将会使用 PHP strtotime
函数验证。
alpha
字段仅全数为字母字串时通过验证。
alpha_dash
字段值仅允许字母、数字、破折号(-)以及底线(_)
alpha_num
字段值仅允许字母、数字
array
字段值仅允许为数组
before:date
验证字段是否是在指定日期之前。这个日期将会使用 PHP strtotime
函数验证。
between:min,max
字段值需介于指定的 min 和 max 值之间。字串、数值或是文件都是用同样的方式来进行验证。
confirmed
字段值需与对应的字段值 foo_confirmation
相同。例如,如果验证的字段是 password
,那对应的字段 password_confirmation
就必须存在且与 password
字段相符。
date
字段值通过 PHP strtotime
函数验证是否为一个合法的日期。
date_format:format
字段值通过 PHP date_parse_from_format
函数验证符合 format 制定格式的日期是否为合法日期。
different:field
字段值需与指定的字段 field 值不同。
digits:value
字段值需为数字且长度需为 value。
digits_between:min,max
字段值需为数字,且长度需介于 min 与 max 之间。
boolean
字段必须可以转换成布尔值,可接受的值为 true
, false
, 1
, 0
, "1"
, "0"
。
email
字段值需符合 email 格式。
exists:table,column
字段值需与存在于数据库 table 中的 column 字段值其一相同。
Exists 规则的基本使用方法
'state' => 'exists:states'
指定一个自定义的字段名称
'state' => 'exists:states,abbreviation'
您可以指定更多条件且那些条件将会被新增至 "where" 查询里:
'email' => 'exists:staff,email,account_id,1'
/* 这个验证规则为 email 需存在于 staff 这个数据库表中 email 字段中且 account_id=1 */
通过NULL
搭配"where"的缩写写法去检查数据库的是否为NULL
'email' => 'exists:staff,email,deleted_at,NULL'
image
文件必需为图片(jpeg, png, bmp, gif 或 svg)
in:foo,bar,...
字段值需符合事先给予的清单的其中一个值
integer
字段值需为一个整数值
ip
字段值需符合 IP 位址格式。