facile-it / php-codec
PHP中对io-ts的部分移植
Requires
- php: ^7.2 | ^8.0
Requires (Dev)
- facile-it/facile-coding-standard: ^0.5.1
- friendsofphp/php-cs-fixer: ^3.3
- giorgiosironi/eris: ^0.13.0
- icomefromthenet/reverse-regex: ^0.1.0
- phpat/phpat: >=0.7.5
- phpunit/php-code-coverage: ^7.0
- phpunit/phpunit: ^8.5
- vimeo/psalm: 4.8.1
Suggests
- ext-json: *
This package is auto-updated.
Last update: 2024-09-10 16:22:08 UTC
README
PHP-codec是io-ts在PHP中的部分移植。
现在就安装它。它只需要PHP >= 7.4。
composer require facile-it/php-codec
免责声明
该项目正在积极开发中:它是不稳定的,且文档记录不完整。API可能会多次更改,并且不久将准备好用于生产。
该项目遵循语义版本控制。
简介
该项目是将出色的io-ts库部分移植到TypeScript的项目。所有内容都围绕着解码器、编码器和编解码器的概念。
解码器可以将值从一种类型转换为另一种类型。这种转换可能会失败。
use Facile\PhpCodec\Validation\Validation; /** * @psalm-template I * @psalm-template A */ interface Decoder { /** * @psalm-param I $i * @psalm-return Validation<A> */ public function decode($i): Validation; /** ... */ }
编码器执行类似的转换,但类型之间不能失败。
/** * @psalm-template A * @psalm-template O */ interface Encoder { /** * @psalm-param A $a * @psalm-return O */ public function encode($a); }
编解码器是解码器和编码器的组合,结合了它们的功能。
我建议阅读io-ts文档中的理念部分。它从一个关于编解码器的美丽描述开始。
Type<A, O, I>
类型的值(称为"编解码器")是静态类型A
的运行时表示。
入门指南
composer require facile-it/php-codec
解码器
解码器是具有解码能力的对象。类型为Decoder<I, A>
的解码器接收类型为I
的输入并构建类型为Validation<A>
的结果。
类Facile\PhpCodec\Decoders
提供了内置解码器和组合器的工厂方法。
如何使用解码器
use Facile\PhpCodec\Decoders; use Facile\PhpCodec\Decoder; use Facile\PhpCodec\Validation\Validation; use Facile\PhpCodec\Validation\ValidationFailures; use Facile\PhpCodec\Validation\ValidationSuccess; /** @var Decoder<string, int> $decoder */ $decoder = Decoders::intFromString(); /** @var Validation<int> $v1 */ $v1 = $decoder->decode('123'); // Since '123' is a numeric string which represents an integer, // then we can expect the decoding to be successful. // Hence, $v1 will be an instance of ValidationSuccess if($v1 instanceof ValidationSuccess) { var_dump($v1->getValue()); } /** @var Validation<int> $v2 */ $v2 = $decoder->decode('hello'); // Similarly, since 'hello' is not a numeric string, we expect // the decoding fail. $v2 will be an instance of ValidationError if($v2 instanceof ValidationFailures) { var_dump($v2->getErrors()); }
处理验证结果
我们可以使用Validation::fold
在任何情况下提供有效结果的同时解构验证结果。
use Facile\PhpCodec\Decoders; use Facile\PhpCodec\Decoder; use Facile\PhpCodec\Validation\Validation; /** @var Decoder<string, int> $decoder */ $decoder = Decoders::intFromString(); Validation::fold( function (\Facile\PhpCodec\Validation\ValidationFailures $failures): int { // I may not care about the error. // Here I want to give a default value when the deconding fails. return 0; }, function (\Facile\PhpCodec\Validation\ValidationSuccess $success): int { return $success->getValue(); }, $decoder->decode($input) );
您可以使用路径报告器为失败构建格式良好的错误消息。
use Facile\PhpCodec\Decoders; $decoder = Decoders::intFromString(); $v = $decoder->decode('hello'); $msgs = \Facile\PhpCodec\Reporters::path()->report($v); var_dump($msgs); /* This will print array(1) { [0] => string(49) "Invalid value "hello" supplied to : IntFromString" } */
示例
查看示例文件夹。
报告器
报告器从Validation
对象创建报告。一般来说,报告器是实现Reporter<T>
接口的对象,其中T
是生成的报告的类型。
一组有趣的报告器是验证错误报告器组。它们实现了Reporter<list<string>>
。因此,给定的一个Validation
对象,它们为每个验证错误生成一个错误消息列表。
PHP-Codec附带两个错误报告器
- PathReporter,它是io-ts的PathReporter的直接移植。
- SimplePathReporter,它是PathReporter的简化版(即:消息更短)。
$d = Decoders::arrayProps([ 'a' => Decoders::arrayProps([ 'a1' => Decoders::int(), 'a2' => Decoders::string(), ]), 'b' => Decoders::arrayProps(['b1' => Decoders::bool()]) ]); $v = $d->decode(['a'=> ['a1' => 'str', 'a2' => 1], 'b' => 2]); $x = \Facile\PhpCodec\Reporters::path()->report($v); // $x will be // ['Invalid value "str" supplied to : {a: {a1: int, a2: string}, b: {b1: bool}}/a: {a1: int, a2: string}/a1: int', // 'Invalid value 1 supplied to : {a: {a1: int, a2: string}, b: {b1: bool}}/a: {a1: int, a2: string}/a2: string', // 'Invalid value undefined supplied to : {a: {a1: int, a2: string}, b: {b1: bool}}/b: {b1: bool}/b1: bool'] $y = \Facile\PhpCodec\Reporters::simplePath()->report($v); // $y will be // ['/a/a1: Invalid value "str" supplied to decoder "int"', // '/a/a2: Invalid value 1 supplied to decoder "string"', // '/b/b1: Invalid value undefined supplied to decoder "bool"']