bytepath/shared

所有Bytepath项目使用的共享库

1.0.5 2023-03-09 18:11 UTC

This package is auto-updated.

Last update: 2024-09-10 20:25:11 UTC


README

此软件包包含我们在每个项目中使用的许多库。这些库是框架无关的,这意味着您通常必须为您选择的框架提供一个实现。

Validator

Validator是一个框架无关的库,用于对客户端数据进行验证。该类提供了一个接口,用于定义验证器的工作方式,以及该接口的抽象实现,您可以使用它来实现应用程序中的验证。

ValidatorInterface

ValidatorInterface有两个方法

    public function rules($rules): self;

    public function validate($data, ?Closure $callback): ValidationResult;

rules()

第一个方法,rules,接受一个$rules列表,并返回您正在使用的验证器的新实例。规则目前没有正式定义。您需要决定哪些是规则。将来我计划添加某种类型的规则定义类,使您的规则更具可移植性。

我使用laravel,因此'methods'对我来说看起来是这样的。

$rules = [
  "name" => "required|string|max:100",
  "age" => "required|numeric",
];

此方法返回一个新类,保留原始类不变,因此您可以在任何时候调用此方法,而无需担心状态等。

validate()

第二个方法,validate,将您的规则应用于提供的$data。如果所有规则都通过且数据被认为是经过验证的,则将运行第二个参数提供的闭包。此闭包仅在验证通过时运行,因此您可以在此处执行“危险”操作,例如在数据库中创建行等。

闭包将传递一个经过验证的$data变量。数据数组中的任何没有相应规则的字段都将被过滤掉,因此您不需要明确检查此点。

$rules = [
  "name" => "required|string|max:100",
  "age" => "required|numeric",
];

$userData = [
  "name" => "andrew",
  "age"  => 12,
  "zip" => "90210" // No rule for this 
];

return $validator->rules($rules)->validate($userData, function($validatedData) {
   // zip will be filtered out of the $validatedData array

   // Returns a theoretical user object containing the validated data
   return App\Models\User::create($validatedData);
});

如果闭包返回一个值,您可以通过此方法返回的ValidationResult对象的getData()方法访问此值。

Validator

Validator是一个抽象类,为您实现ValidatorInterface的大多数工作。尽管建议您将此Validator作为实现的基础,但如果这更适合您的用例,您也可以直接实现ValidationInterface。

此类有一个抽象方法

    abstract protected function checkData($data, $rules): ValidationResult;

该方法在您选择的方法中执行验证操作。您必须自己实现此方法。

此方法返回一个扩展下面描述的ValidationResult类的对象。

ValidationResult

ValidatorInterface的validate方法返回一个扩展抽象ValidationResult类的对象。假设您正在使用此库中预制的Validator类,可以返回两种可能的对象。

PassedValidation

如名称所示,如果提供的数据通过验证,则将返回此对象。此对象将包含您在ValidatorInterface部分中描述的validate()方法传递给闭包返回的任何数据。要访问此数据,您可以在PassedValidation类中运行getData()方法。

FailedValidation

如名称所示,如果提供的数据未通过验证,则将返回此对象。此对象将包含未通过验证的规则列表/值列表以及您可以在表单中提供给用户的可读字符串。您可以使用getErrors()方法访问此错误列表。

在您的应用程序中更改PassedValidation/FailedValidation的行为

您可以从实现 Validator 的任何返回值中返回,只要返回的对象扩展自 ValidationResult。为了使这个过程更简单,Validator 类有两个受保护的方法,您可以重写这些方法来更改在通过/失败的情况下返回的类。

    protected function passed($data = []): PassedValidation
    protected function failed($errors = []): FailedValidation

如果您在自己的实现中扩展了这些方法,则可以更改返回的值。返回的值必须分别扩展 Passed/FailedValidation。

例如,在 Laravel 中,您可以实现 Responsible 接口以自动将这些对象转换为有效的 Laravel 响应对象。现在,您可以直接从控制器方法中返回结果,它将神奇地转换为带有适当头等有效 HTTP 响应。

转换 Validator 返回的数据

ValidationResult 对象有一个名为 transform 的方法,您可以使用它来修改 ValidationResult 对象返回的数据。此类接受一个回调函数,并返回 "self",这意味着您可以直接在实现中链式调用此函数调用。

例如,让我们修改先前的示例,其中我们验证数据并使用它来创建用户。想象一下,我们想返回一个 JSON 字符串而不是对象。我们可以使用 transform 函数这样做:

// Pulled from the validate() example from earlier in this doc
$result = $validator->rules($rules)->validate($data, function($validatedData) {
   return App\Models\User::create($validatedData);
});

// Transforms the "User" into JSON.
$result->transform(function($data) {
 return json_encode($data);
});

// Returns {"name": "andrew", "age": 12}
$shouldBeJSON = $result->getData();

FailedValidation 对象上的 transform() 类

FailedValidation 对象没有要转换的数据,因此如果您在 FailedValidation 对象上调用 transform() 方法,该类将仅返回 self,而不会实际运行回调。

这样做是故意的,这样我们可以在保留转换成功结果的能力的同时返回失败结果。

$failed = $validator->rules($rules)->validate($data, $fn);  // Validation failed here returning a FailedValidation object

$failed->passes(); // False

$failed->transform(function($data) {
   return json_encode($data);   // This function will NOT be ran on FailedValidation so it's safe to assume we have validated data here
});

示例实现

您可以使用上述描述的概念来编写非常详细且易于阅读的代码。以下是一个您可以使用示例实现。

class SomeService
{
    public function __construct(protected Validator $validator)
    {}

    /**
     * Creates a validator, then uses that validator to validate the data 
     * and create a new user
    */
    public function createUser($data): ValidationResult
    {
        return $this->getCreateValidator()->validate($data, function($validatedData) {
            return App\Models\User::create($validatedData);
        });
    }

    /**
     * Creates a validator by passing it a list of rules required to make a new user
    */
    protected function getCreateValidator(): Validator
    {
        $rules = [
            "name" => "required|string|max:100",
            "age" => "required|numeric",
        ];

        return $this->validator->rules($rules);  
    }
}
class SomeController
{
    public function __construct(protected SomeService $service)
    {}

    public function createUserReturnJSON($data)
    {
      /**
        If validation succeeds,we will create a new user and convert it to JSON

        If validation fails, we return a FailedValidation object that contains
        a list of validation errors you can provide to the user. You could
        process these errors here, or catch them in a middleware of some
        sort
      */
      return $this->service->createUser($data)->transform(function($data){
          // This callback will only run if validation was successful
          return json_encode($data);
      });
    }
}