bytepath / shared
所有Bytepath项目使用的共享库
Requires
- php: >=8.0
Requires (Dev)
- phpunit/phpunit: ^10.0
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); }); } }