验证是 Laravel Eloquent 模型的一个特征,可确保模型在保存之前满足其验证标准。如果它们被认为无效,则不会保存模型并且将提供验证错误。
验证允许多个规则集,将模型 ID 注入到unique
验证规则中,并在验证失败时引发异常。它小巧而灵活,适合您的工作流程,并帮助您仅保存有效数据。
希望在 Laravel 4.2+ 上使用验证?查看 0.10.x 分支以获取文档和安装说明。
Laravel 4.2 版本更适合做表单验证;它支持自定义验证消息、确认规则和多个规则集。因为 Laravel 5.0 具有FormRequest
验证,所以验证现在旨在保持核心数据有效并将表单验证留给框架。
想要在 Laravel 5.0 到 5.2 上使用验证?查看 2.x 分支以获取文档和安装说明。
Laravel 5.0 - 5.2 版本使用了 Laravel 框架中已弃用的ValidationException
合约。对于 Laravel 5.3,我们现在扩展了核心验证ValidationException
,这意味着当发生验证错误时,框架将自动重定向回错误,就像FormRequest
一样。
请继续阅读 - 这些说明适合您!
只需转到composer.json
文件所在的项目目录并输入:
作曲家需要沃森/验证
查看 Laravel 4.2+ 的安装说明。查看 Laravel 5.0 - 5.2 的安装说明。
首先,将特征添加到您的模型中,并根据需要添加验证规则和消息。
使用 WatsonValidatingValidatingTrait;class Post 扩展了 Eloquent { 使用 ValidatingTrait; protected $rules = [ 'title' => '必需', 'slug' => '必需|unique:posts,slug', 'content' => '必需' ]; }
如果您使用的是 BaseModel 并且它将适用于从它扩展的所有模型,您还可以将该特征添加到BaseModel
中,否则您可以只扩展WatsonValidatingValidatingModel
而不是Eloquent
。
注意:您需要在从使用该特征的BaseModel
扩展的任何模型上设置$rules
属性,或者设置一个空数组作为BaseModel
的$rules
。如果不这样做,您将不可避免地出现LogicException with message 'Relationship method must return an object of type IlluminateDatabaseEloquentRelationsRelation'
。
现在,您可以使用一些令人愉快的功能。
// 检查模型是否有效。$post->isValid(); // true// 或者检查是否无效。$post->isInvalid(); // false// 一旦确定了模型的有效性,// 您就可以获得错误。$post->getErrors(); // 错误消息包
模型验证也变得非常简单。
if ( ! $post->save()) {// Oops.return redirect()->route('posts.create') ->withErrors($post->getErrors()) ->withInput(); }返回重定向()->路由('posts.show', $post->id) ->withSuccess("您的帖子已成功保存。");
否则,如果您在验证模型时更喜欢使用异常,则可以使用saveOrFail()
方法。现在,当您尝试保存无效模型时,将会引发异常。
$post->saveOrFail();
如果您不想,则无需捕获异常。 Laravel 知道如何处理ValidationException
并会自动重定向回表单输入和错误。如果您想自己处理,也可以。
尝试 {$post->saveOrFail(); } catch (WatsonValidatingValidationException $e) {$errors = $e->getErrors();返回redirect()->route('posts.create') ->withErrors($errors) ->withInput(); }
请注意,您可以将异常传递给withErrors()
方法,例如withErrors($e)
,Laravel 将知道如何处理它。
如果您正在使用该模型并且希望执行绕过验证的保存,则可以。这将返回与在没有特征的模型上调用save()
相同的结果。
$post->forceSave();
如果您希望在使用save()
方法时默认抛出异常,而不是必须使用saveOrFail()
您可以在模型或BaseModel
上设置以下属性。
/** * 如果模型验证失败,是否应抛出 ValidationException。如果不设置,则默认为 false。 * * @var boolean */protected $throwValidationExceptions = true;
如果您想使用异常或返回值执行一次性保存,可以使用saveOrFail()
和saveOrReturn
方法。
要显示自定义验证错误消息,只需将$validationMessages
属性添加到模型中即可。
/** * 要传递给验证器的验证消息。 * * @var array */protected $validationMessages = ['slug.unique' => "另一篇文章已经在使用该 slug。"];
您可能已经注意到,我们在 slug 上使用了unique
规则,如果我们更新持久模型,则该规则将不起作用。幸运的是,验证将为您处理这个问题,并将模型的主键附加到规则中,以便规则按预期工作;忽略当前模型。
您可以通过在模型上设置$injectUniqueIdentifier
属性来调整此功能。
/** * 模型是否应在尝试验证之前将其标识符注入到唯一的 * 验证规则中。如果模型中未设置此属性*,它将默认为 true。 * * @var boolean */protected $injectUniqueIdentifier = true;
开箱即用,我们支持 Laravel 提供的unique
规则。我们还支持流行的 felixkiss/uniquewith-validator 规则,但您需要选择加入。只需在导入验证特征后添加use WatsonValidatingInjectorsUniqueWithInjector
即可。
如果您愿意,支持其他注入规则也很容易。假设您想支持名为unique_ids
附加规则,该规则仅采用模型的主键(无论出于何种原因)。您只需添加一个驼峰式规则,该规则接受任何现有参数和字段名称,并返回替换规则。
/** * 准备一个 unique_ids 规则,如果需要,添加模型标识符。 * * @param array $parameters * @param string $field * @return string */受保护的函数prepareUniqueIdsRule($parameters, $field) {// 仅当模型已持久化时才执行替换。if ($this->exists) {return 'unique_ids:' . $this->getKey(); }返回'unique_ids'; }
在这种情况下,如果模型已保存并且主键为10
,则规则unique_ids
将替换为unique_ids:10
。
在验证过程中,该特征会触发各种事件,您可以挂钩这些事件来影响验证过程。
要挂钩,您首先需要将$observeables
属性添加到您的模型(或基本模型)上。这只是让 Eloquent 知道您的模型可以响应这些事件。
/** * 用户公开的可观察事件 * * @var array */protected $observables = ['validating', 'validated'];
当验证即将发生时, eloquent.validating: ModelName
事件将被触发,其中$event
参数将saving
或restoring
。例如,如果您要更新命名空间模型AppUser
则事件将为eloquent.validating: AppUser
。如果您侦听这些事件中的任何一个并返回一个值,则可以阻止验证完全发生。
event::listen('eloquent.validating:*', function($model, $event) {// 伪俄罗斯轮盘赌validation.if (rand(1, 6) === 1) {return false; } });
验证发生后,您还可以挂钩一系列validated
事件,例如passed
、 failed
和skipped
事件。对于上面验证失败的示例,您可以获得事件eloquent.validated: AppUser
。
目前 Laravel 中存在一个错误(请参阅问题 #1181),该错误会阻止模型事件在测试套件中多次触发。这意味着使用模型测试的第一个测试将通过,但任何后续测试都将失败。该线程中列出了几个临时解决方案,您可以使用它们同时使测试通过。
由于 Laravel 出于跟踪 bug 和拉取请求的目的已改用 Liferaft,因此上述问题可能无法解决。这个要点有一个示例TestCase.php
,它向您展示了如何在测试之间重置所有模型的事件,以便它们按预期工作。
您可以通过多种方式在控制器中使用验证模型,但是这里有一个使用 Laravel 5 中新的 FormRequest 的示例(如果您想查看另一个没有 FormRequest 的控制器示例,请检查该软件包的 4.2+ 版本。
此示例允许 FormRequest 处理表单验证并允许模型处理其自身的验证,从而保持代码整洁。通过启用验证异常,您可以减少重复的控制器代码(try/catch 块)并全局处理模型验证异常(您的表单请求应保持模型有效,因此如果您的模型无效,则这是一个异常事件)。
<?php 命名空间 AppHttpControllers;use AppHttpRequestsPostFormRequest;use IlluminateRoutingController;class PostsController 扩展 Controller {受保护的$post;公共函数__construct(Post $post) {$这个->post = $post; }// ...公共函数存储(PostFormRequest $request) {// 如果 Post 无效,则会抛出异常。$post = $this->post->create($request->input());// Post 保存成功。return redirect()->route( 'posts.show', $post); } }
然后,您可以在app/Exceptions/Handler.php
中捕获模型验证异常并根据需要进行处理。
公共函数渲染($ request,异常$ e) {if ($e instanceof WatsonValidatingValidationException) {return back()->withErrors($e)->withInput(); }parent::render($request, $e); }