coduo/php-matcher
Composer 安装命令:
composer require coduo/php-matcher
包简介
PHP Matcher enables you to match values with patterns
README 文档
README
Library created for testing all kinds of JSON/XML/TXT/Scalar values against patterns.
API:
PHPMatcher::match($value = '{"foo": "bar"}', $pattern = '{"foo": "@string@"}') : bool; PHPMatcher::backtrace() : Backtrace; PHPMatcher::error() : ?string;
It was built to simplify API's functional testing.
- 6.x README PHP >= 8.3 <= 8.5
- 5.x README PHP >= 7.2 < 8.0
- 5.0 README PHP >= 7.2 < 8.0
- 4.0.* README PHP >= 7.2 < 8.0
- 3.2.* README PHP >= 7.0 < 8.0
- 3.1.* README PHP >= 7.0 < 8.0
Sandbox
Feel free to play first with Sandbox
Installation
Require new dev dependency using composer:
composer require --dev "coduo/php-matcher"
Basic usage
Direct PHPMatcher usage
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $match = $matcher->match("lorem ipsum dolor", "@string@"); if (!$match) { echo "Error: " . $matcher->error(); echo "Backtrace: \n"; echo (string) $matcher->backtrace(); }
PHPUnit extending PHPMatcherTestCase
<?php use Coduo\PHPMatcher\PHPUnit\PHPMatcherTestCase; class MatcherTest extends PHPMatcherTestCase { public function test_matcher_that_value_matches_pattern() { $this->assertMatchesPattern('{"name": "@string@"}', '{"name": "Norbert"}'); } }
PHPUnit using PHPMatcherAssertions trait
<?php use Coduo\PHPMatcher\PHPUnit\PHPMatcherAssertions; use PHPUnit\Framework\TestCase; class MatcherTest extends TestCase { use PHPMatcherAssertions; public function test_matcher_that_value_matches_pattern() { $this->assertMatchesPattern('{"name": "@string@"}', '{"name": "Norbert"}'); } }
Available patterns
@string@@integer@@number@@double@@boolean@@time@@date@@datetime@@timezone@||@tz@array@@array_previous@- match next array element using pattern from previous element@array_previous_repeat@- match all remaining array elements using pattern from previous element@...@- unbounded array, once used matcher will skip any further array elements@null@@*@||@wildcard@expr(expression)- optional, requiressymfony/expression-language: ^6.4 || ^7.4 || ^8.0to be present@uuid@@ulid@@json@@string@||@integer@- string OR integer
Available pattern expanders
startsWith($stringBeginning, $ignoreCase = false)endsWith($stringEnding, $ignoreCase = false)contains($string, $ignoreCase = false)notContains($string, $ignoreCase = false)isDateTime()isInDateFormat($format)- example"@datetime@.isInDateFormat('Y-m-d H:i:s')before(string $date)- example"@string@.isDateTime().before(\"2020-01-01 00:00:00\")"after(string $date)- example"@string@.isDateTime().after(\"2020-01-01 00:00:00\")"isTzOffset()isTzIdentifier()isTzAbbreviation()isEmail()isUrl()isIp()isEmpty()isNotEmpty()lowerThan($boundry)greaterThan($boundry)inArray($value)- example"@array@.inArray(\"ROLE_USER\")"hasProperty($propertyName)- example"@json@.hasProperty(\"property_name\")"oneOf(...$expanders)- example"@string@.oneOf(contains('foo'), contains('bar'), contains('baz'))"matchRegex($regex)- example"@string@.matchRegex('/^lorem.+/')"optional()- work's only withArrayMatcher,JsonMatcherandXmlMatchercount()- work's only withArrayMatcher- example"@array@.count(5)"repeat($pattern, $isStrict = true)- example'@array@.repeat({"name": "foe"})'or"@array@.repeat('@string@')"match($pattern)- example{"image":"@json@.match({\"url\":\"@string@.isUrl()\"})"}
Example usage
Scalar matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match(1, 1); $matcher->match('string', 'string');
String matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match('Norbert', '@string@'); $matcher->match("lorem ipsum dolor", "@string@.startsWith('lorem').contains('ipsum').endsWith('dolor')");
Time matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match('00:00:00', '@time@'); $matcher->match('00:01:00.000000', '@time@'); $matcher->match('00:01:00', '@time@.after("00:00:00")'); $matcher->match('00:00:00', '@time@.before("01:00:00")');
Date matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match('2014-08-19', '@date@'); $matcher->match('2020-01-11', '@date@'); $matcher->match('2014-08-19', '@date@.before("2016-08-19")'); $matcher->match('2014-08-19', '@date@.before("today").after("+ 100year")');
DateTime matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match('2014-08-19', '@datetime@'); $matcher->match('2020-01-11 00:00:00', '@datetime@'); $matcher->match('2014-08-19', '@datetime@.before("2016-08-19")'); $matcher->match('2014-08-19', '@datetime@.before("today").after("+ 100year")');
TimeZone matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match('Europe/Warsaw', '@timezone@'); $matcher->match('Europe/Warsaw', '@tz@'); $matcher->match('GMT', '@tz@'); $matcher->match('01:00', '@tz@'); $matcher->match('01:00', '@tz@.isTzOffset()'); $matcher->match('GMT', '@tz@.isTzAbbreviation()'); $matcher->match('Europe/Warsaw', '@tz@.isTzIdentifier()');
Integer matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match(100, '@integer@'); $matcher->match(100, '@integer@.lowerThan(200).greaterThan(10)');
Number matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match(100, '@number@'); $matcher->match('200', '@number@'); $matcher->match(1.25, '@number@'); $matcher->match('1.25', '@number@'); $matcher->match(0b10100111001, '@number@');
Double matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match(10.1, "@double@"); $matcher->match(10.1, "@double@.lowerThan(50.12).greaterThan(10)");
Boolean matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match(true, "@boolean@"); $matcher->match(false, "@boolean@");
Wildcard matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match("@integer@", "@*@"); $matcher->match("foobar", "@*@"); $matcher->match(true, "@*@"); $matcher->match(6.66, "@*@"); $matcher->match(array("bar"), "@wildcard@"); $matcher->match(new \stdClass, "@wildcard@");
Expression matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match(new \DateTime('2014-04-01'), "expr(value.format('Y-m-d') == '2014-04-01'"); $matcher->match("Norbert", "expr(value === 'Norbert')");
UUID matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match('9f4db639-0e87-4367-9beb-d64e3f42ae18', '@uuid@');
ULID matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match('01BX5ZZKBKACTAV9WEVGEMMVS0', '@ulid@');
Array matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match( array( 'users' => array( array( 'id' => 1, 'firstName' => 'Norbert', 'lastName' => 'Orzechowicz', 'roles' => array('ROLE_USER'), 'position' => 'Developer', ), array( 'id' => 2, 'firstName' => 'Michał', 'lastName' => 'Dąbrowski', 'roles' => array('ROLE_USER') ), array( 'id' => 3, 'firstName' => 'Johnny', 'lastName' => 'DąbrowsBravoki', 'roles' => array('ROLE_HANDSOME_GUY') ) ), true, 6.66 ), array( 'users' => array( array( 'id' => '@integer@.greaterThan(0)', 'firstName' => '@string@', 'lastName' => 'Orzechowicz', 'roles' => '@array@', 'position' => '@string@.optional()' ), array( 'id' => '@integer@', 'firstName' => '@string@', 'lastName' => 'Dąbrowski', 'roles' => '@array@' ), '@...@' ), '@boolean@', '@double@' ) );
Array Previous
@array_previous@ can also be used when matching JSON's and XML's
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match( array( 'users' => array( array( 'id' => 1, 'firstName' => 'Norbert', 'lastName' => 'Orzechowicz', 'roles' => array('ROLE_USER'), 'position' => 'Developer', ), array( 'id' => 2, 'firstName' => 'Michał', 'lastName' => 'Dąbrowski', 'roles' => array('ROLE_USER') ), array( 'id' => 3, 'firstName' => 'Johnny', 'lastName' => 'DąbrowsBravoki', 'roles' => array('ROLE_HANDSOME_GUY') ) ), true, 6.66 ), array( 'users' => array( array( 'id' => '@integer@.greaterThan(0)', 'firstName' => '@string@', 'lastName' => 'Orzechowicz', 'roles' => '@array@', 'position' => '@string@.optional()' ), '@array_previous@', '@array_previous@' ), '@boolean@', '@double@' ) );
Array Previous Repeat
@array_previous_repeat@ can also be used when matching JSON's and XML's
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match( array( 'users' => array( array( 'id' => 1, 'firstName' => 'Norbert', 'lastName' => 'Orzechowicz', 'roles' => array('ROLE_USER'), 'position' => 'Developer', ), array( 'id' => 2, 'firstName' => 'Michał', 'lastName' => 'Dąbrowski', 'roles' => array('ROLE_USER') ), array( 'id' => 3, 'firstName' => 'Johnny', 'lastName' => 'DąbrowsBravoki', 'roles' => array('ROLE_HANDSOME_GUY') ) ), true, 6.66 ), array( 'users' => array( array( 'id' => '@integer@.greaterThan(0)', 'firstName' => '@string@', 'lastName' => 'Orzechowicz', 'roles' => '@array@', 'position' => '@string@.optional()' ), '@array_previous_repeat@' ), '@boolean@', '@double@' ) );
Json matching
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match( '{ "users":[ { "firstName": "Norbert", "lastName": "Orzechowicz", "created": "2014-01-01", "roles":["ROLE_USER", "ROLE_DEVELOPER"] } ] }', '{ "users":[ { "firstName": "@string@", "lastName": "@string@", "created": "@string@.isDateTime()", "roles": "@array@", "position": "@string@.optional()" } ] }' );
Json matching with unbounded arrays and objects
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match( '{ "users":[ { "firstName": "Norbert", "lastName": "Orzechowicz", "created": "2014-01-01", "roles":["ROLE_USER", "ROLE_DEVELOPER"], "attributes": { "isAdmin": false, "dateOfBirth": null, "hasEmailVerified": true }, "avatar": { "url": "http://avatar-image.com/avatar.png" } }, { "firstName": "Michał", "lastName": "Dąbrowski", "created": "2014-01-01", "roles":["ROLE_USER", "ROLE_DEVELOPER", "ROLE_ADMIN"], "attributes": { "isAdmin": true, "dateOfBirth": null, "hasEmailVerified": true }, "avatar": null } ] }', '{ "users":[ { "firstName": "@string@", "lastName": "@string@", "created": "@string@.isDateTime()", "roles": [ "ROLE_USER", "@...@" ], "attributes": { "isAdmin": @boolean@, "@*@": "@*@" }, "avatar": "@json@.match({\"url\":\"@string@.isUrl()\"})" } , @...@ ] }' );
Xml matching
Optional - requires openlss/lib-array2xml: ^1.0 to be present.
<?php use Coduo\PHPMatcher\PHPMatcher; $matcher = new PHPMatcher(); $matcher->match(<<<XML <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/stock"> <m:GetStockPrice> <m:StockName>IBM</m:StockName> <m:StockValue>Any Value</m:StockValue> </m:GetStockPrice> </soap:Body> </soap:Envelope> XML , <<<XML <?xml version="1.0"?> <soap:Envelope xmlns:soap="@string@" soap:encodingStyle="@string@"> <soap:Body xmlns:m="@string@"> <m:GetStockPrice> <m:StockName>@string@</m:StockName> <m:StockValue>@string@</m:StockValue> <m:StockQty>@integer@.optional()</m:StockQty> </m:GetStockPrice> </soap:Body> </soap:Envelope> XML );
Example scenario for api in behat using mongo.
@profile, @user Feature: Listing user toys As a user I want to list my toys Background: Given I send and accept JSON Scenario: Listing toys Given the following users exist: | firstName | lastName | | Chuck | Norris | And the following toys user "Chuck Norris" exist: | name | | Barbie | | GI Joe | | Optimus Prime | When I set valid authorization code oauth header for user "Chuck Norris" And I send a GET request on "/api/toys" Then the response status code should be 200 And the JSON response should match: """ [ { "id": "@string@", "name": "Barbie", "_links: "@*@" }, { "id": "@string@", "name": "GI Joe", "_links": "@*@" }, { "id": "@string@", "name": "Optimus Prime", "_links": "@*@" } ] """
PHPUnit integration
The assertMatchesPattern() is a handy assertion that matches values in PHPUnit tests.
To use it either include the Coduo\PHPMatcher\PHPUnit\PHPMatcherAssertions trait,
or extend the Coduo\PHPMatcher\PHPUnit\PHPMatcherTestCase:
namespace Coduo\PHPMatcher\Tests\PHPUnit; use Coduo\PHPMatcher\PHPUnit\PHPMatcherAssertions; use PHPUnit\Framework\TestCase; class PHPMatcherAssertionsTest extends TestCase { use PHPMatcherAssertions; public function test_it_asserts_if_a_value_matches_the_pattern() { $this->assertMatchesPattern('@string@', 'foo'); } }
The matchesPattern() method can be used in PHPUnit stubs or mocks:
$mock = $this->createMock(Foo::class); $mock->method('bar') ->with($this->matchesPattern('@string@')) ->willReturn('foo');
License
This library is distributed under the MIT license. Please see the LICENSE file.
Credits
This lib was inspired by JSON Expressions gem && Behat RestExtension
coduo/php-matcher 适用场景与选型建议
coduo/php-matcher 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 13.2M 次下载、GitHub Stars 达 843, 最近一次更新时间为 2014 年 04 月 25 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「json」 「matcher」 「tests」 「Match」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 coduo/php-matcher 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 coduo/php-matcher 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 coduo/php-matcher 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Generic engine to match identifiers against simple yet powerful patterns
A cli tool which generates unit tests.
Kinikit - PHP Application development framework MVC component
AppVerk extension of PHP Matcher, it enables you to match values with patterns
Implementation of cookie path matching specified in RFC6265
For cookie domain and url comparisons
统计信息
- 总下载量: 13.2M
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 846
- 点击次数: 24
- 依赖项目数: 47
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2014-04-25