ahmedzidan/tmp-watson-validating

Eloquent 模型验证特性。

6.0.8 2022-03-20 20:15 UTC

README

临时将包名更改为 "rinvex/tmp-watson-validating",以便在 Packagist 上发布。

这是直到作者发布新版本前的临时分支,完全支持 Laravel v8+

Validating,Laravel 的验证特性。

Build Status Total Downloads Latest Stable Version Latest Unstable Version License

Validating 是一个为 Laravel Eloquent 模型提供的特性,它确保模型在保存之前满足其验证标准。如果模型被认为无效,则不会保存模型,并且将提供验证错误。

Validating 允许多个规则集,将模型 ID 注入 unique 验证规则,并在验证失败时抛出异常。它小巧灵活,可以很好地融入你的工作流程,帮助你仅保存有效数据。

Laravel 4.2+

想要在 Laravel 4.2+ 上使用 Validating?请查看 0.10.x 分支的文档和安装说明

Laravel 4.2 版本更适合进行表单验证;它支持自定义验证消息、确认规则和多个规则集。由于 Laravel 5.0 有 FormRequest 验证,Validating 现在旨在保持核心数据的有效性,并将表单验证留给框架。

Laravel 5.0 - 5.2

想要在 Laravel 5.0 到 5.2 上使用 Validating?请查看 2.x 分支的文档和安装说明

Laravel 5.0 - 5.2 版本使用了已弃用的 Laravel 框架中的 ValidationException 合同。对于 Laravel 5.3,我们现在扩展了核心验证 ValidationException,这意味着当发生验证错误时,框架会自动返回错误,就像 FormRequest 一样。

Laravel 5.3+

请继续阅读 - 这些说明是为您准备的!

安装

只需进入你的项目目录,其中包含 composer.json 文件,然后输入

composer require watson/validating

查看 Laravel 4.2+ 的安装说明查看 Laravel 5.0 - 5.2 的安装说明

概述

首先,将特性添加到你的模型中,并添加所需的验证规则和消息。

use Watson\Validating\ValidatingTrait;

class Post extends Eloquent
{
	use ValidatingTrait;

	protected $rules = [
		'title'   => 'required',
		'slug'    => 'required|unique:posts,slug',
		'content' => 'required'
	];
}

如果你正在使用 BaseModel,也可以将特性添加到其中,它将适用于所有从它扩展出来的模型。否则,你可以直接从 Eloquent 扩展 Watson\Validating\ValidatingModel

注意:你需要为使用该特性的所有从 BaseModel 扩展的模型设置 $rules 属性,或者为 BaseModel 设置空的 $rules 数组。如果不这样做,你将不可避免地遇到 LogicException with message 'Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation'

现在,你可以访问一些令人愉快的功能。

// Check whether the model is valid or not.
$post->isValid(); // true

// Or check if it is invalid or not.
$post->isInvalid(); // false

// Once you've determined the validity of the model,
// you can get the errors.
$post->getErrors(); // errors MessageBag

模型验证也变得非常简单。

if ( ! $post->save()) {
    // Oops.
    return redirect()->route('posts.create')
        ->withErrors($post->getErrors())
        ->withInput();
}

return redirect()->route('posts.show', $post->id)
    ->withSuccess("Your post was saved successfully.");

否则,如果你更喜欢在验证模型时使用异常,你可以使用 saveOrFail() 方法。现在,当你尝试保存无效模型时,将抛出异常。

$post->saveOrFail();

如果你 不想 捕获异常,Laravel 知道如何处理 ValidationException,并将自动返回表单输入和错误。如果你想要自行处理它,你也可以。

try {
    $post->saveOrFail();

} catch (Watson\Validating\ValidationException $e) {
    $errors = $e->getErrors();

    return redirect()->route('posts.create')
        ->withErrors($errors)
        ->withInput();
}

请注意,您可以直接将异常传递给 withErrors() 方法,例如 withErrors($e),Laravel 将知道如何处理它。

绕过验证

如果您正在使用模型并且希望执行绕过验证的保存操作,您可以这样做。这将返回与在未使用特性时调用 save() 方法相同的结果。

$post->forceSave();

默认验证异常

如果您希望在默认情况下使用 save() 方法抛出异常,而不是使用 saveOrFail(),您只需在您的模型或 BaseModel 上设置以下属性。

/**
 * Whether the model should throw a ValidationException if it
 * fails validation. If not set, it will default to false.
 *
 * @var boolean
 */
protected $throwValidationExceptions = true;

如果您想使用异常或返回值进行一次性保存,可以使用 saveOrFail()saveOrReturn 方法。

验证消息

要显示自定义验证错误消息,只需将 $validationMessages 属性添加到您的模型中。

/**
 * Validation messages to be passed to the validator.
 *
 * @var array
 */
protected $validationMessages = [
    'slug.unique' => "Another post is using that slug already."
];

唯一规则

您可能已经注意到我们在 slug 上使用了 unique 规则,如果我们正在更新一个持久化的模型,这将不起作用。幸运的是,验证将为您处理这个问题,并将模型的键追加到规则中,以便该规则按预期工作;忽略当前模型。

您可以通过在您的模型上设置 $injectUniqueIdentifier 属性来调整此功能。

/**
 * Whether the model should inject it's identifier to the unique
 * validation rules before attempting validation. If this property
 * is not set in the model it will default to true.
 *
 * @var boolean
 */
protected $injectUniqueIdentifier = true;

默认情况下,我们支持 Laravel 提供的 unique 规则。我们还支持流行的 felixkiss/uniquewith-validator 规则,但您需要选择加入。在导入验证特性后,只需添加 use \Watson\Validating\Injectors\UniqueWithInjector

如果您喜欢,也可以轻松支持其他注入规则。比如说,您想要支持一个名为 unique_ids 的额外规则,该规则仅接受模型的主键(出于某种原因)。您只需添加一个接受任何现有参数和字段名称的 camel-cased 规则,并返回替换规则。

/**
 * Prepare a unique_ids rule, adding a model identifier if required.
 *
 * @param  array  $parameters
 * @param  string $field
 * @return string
 */
protected function prepareUniqueIdsRule($parameters, $field)
{
    // Only perform a replacement if the model has been persisted.
    if ($this->exists) {
        return 'unique_ids:' . $this->getKey();
    }

    return 'unique_ids';
}

在这种情况下,如果模型已被保存并具有主键 10,则规则 unique_ids 将替换为 unique_ids:10

事件

在验证过程中,特性会触发各种事件,您可以挂钩到这些事件以影响验证过程。

要挂钩,首先需要将 $observeables 属性添加到您的模型(或基本模型)中。这仅仅让 Eloquent 知道您的模型可以响应这些事件。

/**
 * User exposed observable events
 *
 * @var array
 */
protected $observables = ['validating', 'validated'];

当验证即将发生时,将触发 eloquent.validating: ModelName 事件,其中 $event 参数将是 savingrestoring。例如,如果您正在更新一个命名空间化的模型 App\User,事件将是 eloquent.validating: App\User。如果您监听这些事件之一并返回一个值,则可以完全阻止验证发生。

Event::listen('eloquent.validating:*', function($model, $event) {
    // Pseudo-Russian roulette validation.
    if (rand(1, 6) === 1) {
        return false;
    }
});

验证发生后,还可以挂钩到一系列的 validated 事件,包括 passedfailedskipped 事件。对于上述示例,失败的验证可以获取事件 eloquent.validated: App\User

测试

目前 Laravel 中存在一个错误(请参阅问题 #1181),该错误阻止模型事件在测试套件中多次触发。这意味着第一个使用模型测试的测试将通过,但任何后续测试都将失败。在该线程中列出了几个临时解决方案,您可以使用这些解决方案在同时使测试通过。

由于 Laravel 已切换到 Liferaft 用于跟踪错误和拉取请求,上述提到的错误可能不可用。有关如何重置所有模型在测试之间的事件的示例,请参阅 此 Gist,该 Gist 展示了如何重置所有模型的 TestCase.php,以便它们按预期工作。

控制器使用

在您的控制器中使用验证模型的方式有很多,但这里有一个使用Laravel 5中新的FormRequest的示例(如果您想看一个不使用FormRequest的控制器示例,请查看此包的4.2+版本)。

此示例通过允许FormRequest处理表单验证,模型处理自己的验证,从而保持代码的整洁。通过启用验证异常,您可以减少重复的控制器代码(try/catch块),并全局处理模型验证异常(您的表单请求应该保持模型有效,因此如果模型变得无效,它是一个例外事件)。

<?php namespace App\Http\Controllers;

use App\Http\Requests\PostFormRequest;
use Illuminate\Routing\Controller;

class PostsController extends Controller
{
    protected $post;

    public function __construct(Post $post)
    {
        $this->post = $post;
    }

    // ...

    public function store(PostFormRequest $request)
    {
        // Post will throw an exception if it is not valid.
        $post = $this->post->create($request->input());

        // Post was saved successfully.
        return redirect()->route('posts.show', $post);
    }
}

然后您可以在app/Exceptions/Handler.php中捕获模型验证异常,并按需处理它。

public function render($request, Exception $e)
{
    if ($e instanceof \Watson\Validating\ValidationException) {
        return back()->withErrors($e)->withInput();
    }

    parent::render($request, $e);
}