提及 / kebab
围绕 PHP 标准库的功能,专注于安全性和可测试性的包装器
Requires
- php: >=8.1
- beberlei/assert: ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.6
- phing/phing: ^2.16
- phpstan/phpstan: ^1.4.6
- phpstan/phpstan-beberlei-assert: ^1.0
- phpstan/phpstan-strict-rules: ^1.0
- phpunit/phpunit: ^9.0
- squizlabs/php_codesniffer: ^3.4
README
Kebab 是围绕 PHP 标准库的一些功能的集合,提供了安全包装和测试工具。它非常有用,以至于我们希望将其用于所有地方,包括我们的个人项目。因此,我们无法将其保留给自己。
安装
composer require mention/kebab
目标
本包的目标是
- 提供默认安全(通过在出错时抛出异常)的包装器
- 提供具有更好 API 的包装器
- 让静态分析器满意
- 让测试更容易
PHP 标准库中的一些函数具有臭名昭著的糟糕 API。例如,json_decode()
:如果出错,或 JSON 字符串是 NULL
文字面量,则返回 null
。该包提供了合理的包装器,可以自动检查错误并在失败时抛出异常。该包还提供了一些不太损坏的函数(如 file_get_contents()
)的包装器,因为错误时抛出异常是有用的。
包装器不仅检查错误,还尝试改进 API。例如,json_decode()
有两种变体:JsonUtils::decodeArray()
和 JsonUtils::decodeObject()
。
所有包装器都有静态、单返回类型,以使静态分析器满意。例如,有 Clock::microtimeFloat()
和 Clock::microtimeString()
而不是返回两种可能类型的单个函数。
最后,该包提供了一些工具以使测试更容易,例如允许在测试期间伪造系统时间的 Clock
类。
概述
时钟
时钟以允许在测试期间返回伪造时间(以及系统时间)的方式包装了 time()
、microtime()
、sleep()
、usleep()
。
示例
<?php Clock::enableMocking(946681200); // 946681200 can be any arbitrary timestamp Clock::time(); // int(946681200) Clock::microtimeFloat(); // float(946681200.0) Clock::usleep(5500000); // returns immediately (no actual sleep) Clock::microtimeFloat(); // float(946681205.5) : clock has advanced by 5500000 micro seconds Clock::disableMocking();
在调用 enableMocking()
之前,Clock
方法返回真实系统时间,并且睡眠函数实际上暂停程序,如预期。调用 enableMocking()
后,将返回伪造的时间,并且睡眠函数将推进伪造时间而不实际暂停程序。
这主要受到 Symfony 的 ClockMock
类的启发。
Date\DateUtils
DateUtils
提供了一些日期创建方法。该类使用 Clock
来获取系统时间,因此其结果可以在测试中受控和预测。
<?php DateUtils::now(); // Same as new \DateTimeImmutable(); DateUtils::nowMutable(); // Same as new \DateTime(); DateUtils::nowTz($timezone); // Same as new \DateTimeImmutable('now', $timezone); DateUtils::fromString($dateString); // Same as new \DateTimeImmutable($dateString); DateUtils::fromString($dateString, $format); // Same as \DateTimeImmutable::createFromFormat($format, $dateString); DateUtils::fromStringMutable($dateString); // Same as new \DateTime($dateString); DateUtils::fromStringMutable($dateString, $format); // Same as \DateTime::createFromFormat($format, $dateString); DateUtils::fromStringTz($dateString, $timezone); // Same as new \DateTimeImmutable($dateString, $timezone); DateUtils::fromStringTz($dateString, $timezone, $format); // Same as \DateTimeImmutable::createFromFormat($format, $dateString, $timezone); DateUtils::fromTimestamp($timestamp); // Same as \DateTimeImmutable::createFromFormat("|U", (string) $timestamp); DateUtils::fromTimestamp($timestamp, $micro); // Same as \DateTimeImmutable::createFromFormat("U u", "$timestamp $micro");
File\FileUtils
此类提供了一些在失败时抛出异常的文件函数。
<?php FileUtils::read($file); // Reads file $file, throws exception on failure FileUtils::open($file, $mode); // Opens file $file, throws exception on failure
Json\JsonUtils
此类提供了一些在失败时抛出异常(无效参数、无效正则表达式等)的 JSON 函数,并带有略微改进的接口。
<?php JsonUtils::encode($value); // json_encode, with exceptions on failure JsonUtils::encodePretty($value); // returns pretty-printed JSON, throw exceptions on failure JsonUtils::prettify($json); // prettifies a JSON string JsonUtils::decodeObject($json); // decodes a JSON string, use stdClass to represent JSON objects (same as json_decode($value, false)) JsonUtils::decodeArray($json); // decodes a JSON string, use arrays to represent JSON objects (same as json_decode($value, true))
Log\LogUtils
可以使用 LogUtils::truncate()
方法来防止记录过长的值。默认情况下,它将给定的字符串截断到 255 字节。可以通过将 NO_TRUNCATE_LOG
环境变量设置为 1
来禁用截断。
<?php LogUtils::truncate($veryLargeString); // Truncates to 255 characters by default.
Pcre\PcreUtils
此类提供了具有更好 API 的 PCRE/preg 包装器
- 在出错时抛出异常(无效参数、无效正则表达式等)
- 返回静态,单类型
字符串替换
<?php // Only accept string as subject and returns a string PcreUtils::replace('/bar/', 'foo', 'foobarbaz'); // Only accept array as subject and returns an array PcreUtils::replaceMultiple('/foo/', 'bar', ['foo', 'foo']); // Only accept string as subject and returns a string PcreUtils::replaceArray(['/foo/' => 'bar'], 'foo'); // Only accept array as subject and returns an array PcreUtils::replaceArrayMultiple(['/foo/' => 'bar'], ['foo', 'foo']);
回调替换
<?php // Only accept string as subject and returns a string PcreUtils::replaceCallback('/\d/', $callback, '123'); // Only accept array as subject and returns an array PcreUtils::replaceCallbackMultiple('/\d/', $callback, ['1', '2']); // Only accept string as subject and returns a string PcreUtils::replaceCallbackArray($patternsAndCallbacks, '123'); // Only accept array as subject and returns an array PcreUtils::replaceCallbackArrayMultiple($patternsAndCallbacks, ['1', '2']);
过滤器替换
<?php // Only accept string as subject and returns a string PcreUtils::filter('/bar/', 'foo', 'foobarbaz'); // Only accept array as subject and returns an array PcreUtils::filterMultiple('/foo/', 'bar', ['foo', 'foo']); // Only accept string as subject and returns a string PcreUtils::filterArray(['/foo/' => 'bar'], 'foo'); // Only accept array as subject and returns an array PcreUtils::filterArrayMultiple(['/foo/' => 'bar'], ['foo', 'foo']);
其他方法
<?php // Always returns a boolean or throws on error PcreUtils::match('/bar/', 'foobarbaz'); // Returns number of hits that matched or throws on error PcreUtils::matchAll('/foo/', 'foobarbaz'); // Split string by a regular expression PcreUtils::split('/\d/', 'foo1bar2baz'); // Quote regular expression characters PcreUtils::quote('foo$bar');
作者
提及 团队和贡献者