philiagus / parser
PHP 输入断言、解析和转换类。
v1.2.0
2020-11-09 10:45 UTC
Requires
- php: >=7.2
- ext-json: *
- ext-mbstring: *
Requires (Dev)
- ext-xdebug: *
- phpunit/phpunit: *
This package is auto-updated.
Last update: 2024-09-03 14:57:55 UTC
README
PHP 类用于断言、转换和解析数据。
是否经过测试?
在以下 PHP 版本上进行了测试
- PHP8.3
100% 测试覆盖率。测试覆盖率在 PHP8.3 上生成
我为什么需要它?
确保您的输入是预期的,是安全编码的核心原则之一。
显然还有很多,但我们必须一步一步地解决它们。
解析器的基本思想是,开发者通过代码定义一个结构,然后向它投掷一组数据。解析器确保数据遵循结构中定义的规则。
它是如何工作的?
有关如何编写自己的解析器的更深入文档和教程,请参阅这里。
一个简单的例子,断言提供的值在定义的范围内
<?php use Philiagus\Parser\Base\Subject; use Philiagus\Parser\Parser\Assert\AssertInteger; $integer = 100; $parsingResult = AssertInteger::range(0, 100) ->parse(Subject::default($integer)) ->getValue(); // or, also possible: AssertInteger::range(0, 100) ->thenAssignTo($target) ->parse(Subject::default($integer)) ->getValue();
当你开始将解析器堆叠在一起时,真正的乐趣才开始。
<?php use Philiagus\Parser\Base\Subject; use Philiagus\Parser\Parser\Assert\AssertFloat; use Philiagus\Parser\Parser\Assert\AssertInteger; use Philiagus\Parser\Parser\Logic\OneOf; use Philiagus\Parser\Parser\Parse\ParseArray; $input = [ 1, 1.0, 2, 4, 4.20 ]; $integers = []; $floats = []; ParseArray::new() ->assertSequentialKeys() ->giveEachValue( OneOf::new() ->parser( AssertInteger::minimum(0) ->thenAppendTo($integers), AssertFloat::minimum(0.0) ->thenAppendTo($floats) ) ) ->parse(Subject::default($input)); // $integers will contain [1, 2, 4] // $floats will contain [1.0, 4.20]
比如说:您有一个 API,它以 JSON 格式从客户端接收请求,并且您需要找到相关信息。
<?php use Philiagus\Parser\Base\Subject; use Philiagus\Parser\Parser\Assert\AssertInteger; use Philiagus\Parser\Parser\Assert\AssertStdClass; use Philiagus\Parser\Parser\Assert\AssertStringMultibyte; use Philiagus\Parser\Parser\Convert\ConvertToDateTime; use Philiagus\Parser\Parser\Parse\ParseJSONString; $sourceValue = '{"name":"Frank Herbert","birthday":"1920-10-08"}'; $parser = ParseJSONString::new() ->then( AssertStdClass::new() ->givePropertyValue( 'name', AssertStringMultibyte::UTF8() ->giveLength( AssertInteger::new() ->assertMinimum(1) ->assertMaximum(64) ) ->thenAssignTo($name) ) ->givePropertyValue( 'birthday', ConvertToDateTime::fromSourceFormat( '!Y-m-d', new \DateTimeZone('UTC'), 'The provided birthday is not a valid date' ) ->setTimezone(new \DateTimeZone('UTC')) ->thenAssignTo($birthday) ) ); $result = $parser->parse(Subject::default($sourceValue, 'Input', false)); if ($result->hasErrors()) { foreach ($result->getErrors() as $error) { echo $error->getPathAsString(), ': ', $error->getMessage(), PHP_EOL; } exit; } $today = new \DateTime(); $delta = $today->diff($birthday); if ($today < $birthday) { echo "$name will be born in ", $delta->y, " years", PHP_EOL; } else { echo "$name was born ", $delta->y, " years ago", PHP_EOL; }
如果您执行此代码,结果将是“弗兰克·赫伯特出生于101年前”(至少在这次输入时是这样)。
如果将输入更改为{"name":123,"birthday":"1920-10-0f"}
,结果将是
Input.name: Provided value is not of type string
Input.birthday: The provided birthday is not a valid date
如果某些信息缺失怎么办?
不用担心!所有解析器都实现了Philiagus\Parser\Contract\Parser
,因此您可以轻松编写自己的解析器来满足特定的需求。请查看Philiagus\Parser\Base\Parser
,它是一个可以轻松扩展的基类。
一些提示
- 如果您的解析器验证类型(例如:读取 XML 的解析器,因此非字符串是不允许的),则
Philiagus\Parser\Base\OverwritableTypeErrorMessage
特质可能有所帮助。 Philiagus\Parser\Base\Parser
已经实现了基本功能,如使用->then($parser)
进行链式调用等,因此您不必担心这些问题。- 如果您需要更多控制解析器的行为或不喜欢
ResultBuilder
,只需实现Philiagus\Parser\Contract\Parser
接口即可与其他解析器互操作。只需注意,您必须- 当您进入解析器时创建一个
ParserBegin
主题,将提供的主题包装在另一个主题中,以确保值链保持不变 - 尊重主题的
throwOnError()
信息:如果发生错误并且throwOnError()
处于活动状态,您必须抛出错误(通常使用$error->throw()
)。相应地,如果throwOnError()
未处于活动状态,您必须将错误添加到结果对象中。
- 当您进入解析器时创建一个