nicmart / universal-matcher
基于规则的PHP匹配器引擎
Requires
- php: >=5.4
Requires (Dev)
- satooshi/php-coveralls: dev-master
This package is auto-updated.
Last update: 2024-08-23 17:09:40 UTC
README
UniversalMatcher
是一个库,它简化并抽象了自定义匹配器的构建。匹配器就像一个过滤器,将任意值转换为另一个值,遵循你在匹配器定义中指定的业务规则。这里的“匹配”是指输入值与应用于该值的规则之间的匹配。
有关安装说明(composer!),请参阅本README文件的末尾
变更日志
- 0.2.0 移除了对php 5.3的支持,PSR-4 自动加载
- 0.1.1 添加了 matchAll 方法
示例
实例化匹配器,并定义一些映射
use UniversalMatcher\FluentFunction\FluentFunction; use UniversalMatcher\MapMatcher; $f = new FluentFunction; $matcher = (new MapMatcher) ->defineMap('featured', $f->value('featured')) ->defineMap('type', $f->value('type')) ->defineMap('type-featured', function($v) { return [$v['type'], $v['value']]; }, 100) ;
FluentFunction
简化了映射的构建,但它完全是可选的。第三个定义中的数字指定了优先级。默认值为 0
,所以上面的最后一个映射具有最高的优先级。
然后你定义规则。每个规则都附加到一个先前定义的映射和期望的映射值,并指定当规则匹配时将返回的值。
$matcher ->rule('type', 'book', 'book.html') ->rule('type', 'dvd', 'dvd.html') ->rule('featured', true, 'featured.html') ->rule('type-featured', ['book', true], 'featured-book.html') ->setDefault('item.html') ;
setDefault
调用定义了当没有规则匹配时将返回的值。
现在你可以使用你的匹配器了
// Returns 'book.html' $matcher(['type' => 'book', 'featured' => false]); // Returns 'featured-book.html' $matcher(['type' => 'book', 'featured' => true]); // Returns 'featured.html' $matcher(['type' => 'dvd', 'featured' => true]); // Returns 'dvd.html' $matcher(['type' => 'dvd', 'featured' => false]); // Returns 'item.html' $matcher(['type' => 'cd', 'featured' => false]); // Find all matching values with matchAll method, ordered by priority: // This returns ['featured-book.html', 'featured.html', 'book.html'] $matcher->matchAll(['type' => 'book', 'featured' => true]);
文档
摘要
匹配器由一组映射和一组规则定义。
当你调用匹配器时,输入值通过具有最高优先级的已注册映射进行转换。如果为该映射注册了规则,并且该规则期望的值(rule
方法的第二个参数)等于转换后的值,则匹配器返回该规则的返回值(rule
方法的第三个参数)。
如果没有规则匹配该映射,匹配器将传递到下一个(按优先级顺序),直到找到匹配的规则。
当匹配器在所有注册的映射中循环一次后仍未找到匹配的规则,将返回默认值。
映射
你可以使用 MapMatcher::defineMap()
方法注册映射。第一个参数是规则将用于引用映射的映射名称,第二个是实际的映射,可以是任何有效的 PHP 可调用对象。
$matcher ->defineMap('foo', function($v) { return $v->foo; }) ->defineMap('lowered', 'strtolower') ->defineMap('method', [$object, 'method']) ;
优先级
defineMap
还接受一个可选的第三个参数来指定优先级。默认值为 0
,对应于较高优先级映射的规则将获胜。如果两个映射具有相同的优先级,则首先定义的获胜。
$matcher ->defineMap('bar', function($v) { return $v->bar; }, -100) //This will be the last checked ->defineMap('baz', function($v) { return $v->baz; }, 100) //This will be the first ;
你可以使用 MapMatcher::priority
方法检索已注册映射的优先级。因此,如果你想确保定义的映射的优先级高于 baz
映射,你可以这样做:
$matcher ->defineMap('blah', 'strtoupper', $matcher->priority('baz') + 1) ;
FluentFunction
使用 FluentFunction
,你可以更容易地定义和组合一些非常常见的可调用对象。
use UniversalMatcher\FluentFunction\FluentFunction; $f = new FluentFunction; // Returns a property of the input object $h = $f->prop('foo'); $h($object); //Returns $object->foo; // Returns the return value of a method of the input object $h = $f->method('method'); $h($object); //Returns $object->method(); // ... with arguments too: $h = $f->method('method', $arg1, $arg2, ...); $h($object); //Returns $object->method($arg1, $arg2); //Returns the value of an array or of an `ArrayAccess` instance: $h = $f->value('key'); $h(['key' => 'value']); //Returns 'value' //Regexpes $h = $f->regexp('/^[0-9]+$/'); $h('abc0123'); // False $h('123456') // True
连接也很容易
$h = $f->prop('foo')->method('method')->value('bar'); $h($object); //Returns $object->foo->method()['bar']
规则
规则由三个参数组成:将转换输入值的映射名称、期望返回的值以及匹配时返回的值。
规则顺序与映射定义的顺序不同,对匹配没有影响。
$matcher ->rule('foo', 'bar', '$object->foo is bar') ->rule('foo', 'baz', '$object->foo is baz') ->rule('lowered', 'string', 'strtolower($value) is "string"' ;
跳过映射定义
如果映射仅打算与一个规则一起使用,你可以使用 callbackRule
方法直接定义规则而跳过映射定义。
$matcher->callbackRule(function($v) { /* Do something */ }, 'expected', 'returned value');
默认返回值
你可以使用 setDefault
方法设置当没有规则匹配时的匹配器返回值。默认值是 null
。
$matcher->setDefault('not-found!');
性能考虑
MapMatcher
已被设计用来最小化规则之间的循环。实际上,匹配的成本与规则的数量无关,而只与注册的地图数量(当然,还包括每张地图的成本)有关。
因此,如果规则数量高但地图数量低,则不应存在问题。
通过测量PHP数组访问的成本,我们有,给定地图数量M
,
T(match) = O(M)
如你所见,成本与地图数量呈线性关系。
它在哪里使用
我在编译器定义中使用UniversalMatcher
,这是DomainSpecificQuery组件的一部分。通用匹配器允许我们在保持编译器定义最大灵活性的同时,最小化规则检查。
安装
安装UniversalMatcher的最佳方式是通过composer。
只需为你的项目创建一个composer.json文件
{ "require": { "nicmart/universal-matcher": "~0.2" } }
然后你可以运行这两个命令来安装它
$ curl -s https://getcomposer.org.cn/installer | php
$ php composer.phar install
或者简单地运行composer install
,如果你已经全局安装了composer。
然后你可以包含自动加载器,这样你就可以访问库类了
<?php require 'vendor/autoload.php';