arekx/array-expression-engine

数组表达式引擎解析器

1.1.2 2019-05-02 02:11 UTC

This package is auto-updated.

Last update: 2024-09-13 23:02:44 UTC


README

Scrutinizer Code Quality Build Status Code Coverage

这是一个数组表达式解析器,可以用于解析使用PHP数组中指定的配置进行配置的值。这些数组可以从任何地方加载,例如JSON字符串、PHP文件等。

这些表达式用于配置表达式解析引擎,该引擎通过数组表达式中的规则运行值以返回结果。

安装

在您的项目中运行 composer require arekx/array-expression-engine

用法

$isAStark = [
    'or',
    [
        'and',
        ['compare', ['get', 'first'], 'in', ['value', ['Arya', 'Sansa']]],
        ['compare', ['get', 'last'], '=', ['value', 'Stark']],
    ],
    ['regex', ['get', 'emblem'], '/stark/i']
];

$evaluator = \ArekX\ArrayExpression\Evaluator::create();

$values = [
    ['first' => 'John', 'last' => 'Snow', 'emblem' => 'stark'],
    ['first' => 'Arya', 'last' => 'Stark', 'emblem' => 'stark'],
    ['first' => 'Sansa', 'last' => 'Stark', 'emblem' => 'stark'],
    ['first' => 'Joffrey', 'last' => 'Lannister', 'emblem' => 'lannister']
];

foreach ($values as $value) {
    var_dump($evaluator->run($isAStark, $value));
}

// Output: bool(true), bool(true), bool(true), bool(false)

运算符

摘要

以下运算符可用

AND 运算符

AND 运算符在 ArekX\ArrayExpression\Operators\AndOperator 类中定义,用于表示两个或多个表达式之间的 AND 操作,这些表达式可以是任何其他运算符,包括 AND 运算符。

示例

$nameMustBeTestAndAgeAbove2 = ['and', ['compare', ['get', 'name'], ['value', 'test']], ['compare', ['get', 'age'], '>', ['value', 2]]];

$evaluator = \ArekX\ArrayExpression\Evaluator::create();

$evaluator->run($nameMustBeTestAndAgeAbove2, ['name' => 'test', 'age' => 1]); // returns false
OR 运算符

OR 运算符在 ArekX\ArrayExpression\Operators\OrOperator 类中定义,用于表示两个或多个表达式之间的 OR 操作,这些表达式可以是任何其他运算符,包括 OR 运算符。

示例

$nameMustBeTestOrAgeAbove2 = ['or', ['compare', ['get', 'name'], ['value', 'test']], ['compare', ['get', 'age'], '>', ['value', 2]]];

$evaluator = \ArekX\ArrayExpression\Evaluator::create();

$evaluator->run($nameMustBeTestOrAgeAbove2, ['name' => 'test', 'age' => 1]); // returns true
XOR 运算符

XOR 运算符在 ArekX\ArrayExpression\Operators\XOrOperator 类中定义,用于表示两个或多个表达式之间的 XOR 操作,这些表达式可以是任何其他运算符,包括 XOR 运算符。

示例

$nameMustBeTestXOrAgeAbove2 = ['xor', ['compare', ['get', 'name'], ['value', 'test']], ['compare', ['get', 'age'], '>', ['value', 2]]];

$evaluator = \ArekX\ArrayExpression\Evaluator::create();

$evaluator->run($nameMustBeTestXOrAgeAbove2, ['name' => 'test', 'age' => 2]); // returns false
NOT 运算符

NOT 运算符在 ArekX\ArrayExpression\Operators\NotOperator 类中定义,用于表示 NOT 操作或对传递给它的表达式的取反。

示例

$expression = ['not', ['or', ['compare', ['get', 'name'], ['value', 'test']], ['compare', ['get', 'age'], '>', ['value', 2]]]];

$evaluator = \ArekX\ArrayExpression\Evaluator::create();

$evaluator->run($expression, ['name' => 'test', 'age' => 5]); // returns false
BETWEEN 运算符

BETWEEN 运算符在 ArekX\ArrayExpression\Operators\BetweenOperator 类中定义,用于检查一个值是否在最小值和最大值之间。

示例

$expression = ['between', ['get', 'age'], ['value', 1], ['value', 20]]; // Check if age is >= 1 and <= 20

$evaluator = \ArekX\ArrayExpression\Evaluator::create();

$evaluator->run($expression, ['age' => 5]); // returns true
COMPARE 运算符

比较两个表达式的比较运算符。它在 ArekX\ArrayExpression\Operators\CompareOperator 中定义。

比较运算符接受多种格式

短格式

['compare', <expressionA>, <expressionB>]

检查 <expressionA> 是否等于(严格)<expressionB>

关系格式

['compare', <expressionA>, '>=', <expressionB>]

检查 <expressionB> 是否大于或等于 <expressionB> 并返回 true/false

支持的关系运算符

  • > - 大于
  • >= - 大于或等于
  • < - 小于
  • <= - 小于或等于
  • <> - 不等于
  • in - 是值之一。例如 ['compare', <expressionA>, ['value', [1,2,10]]] 检查 <expressionA> 是否为 1210

示例

$expression = ['compare', ['get', 'name'], ['value', 'test']];

$evaluator = \ArekX\ArrayExpression\Evaluator::create();

$evaluator->run($expression, ['name' => 'test', 'age' => 5]); // returns true
REGEX 运算符

REGEX 运算符在 ArekX\ArrayExpression\Operators\RegexOperator 类中定义,用于检查一个值是否与特定的正则表达式模式匹配。

REGEX 运算符接受多种格式

字符串格式

['regex', <expression>, '/pattern/']

检查 <expression> 是否匹配特定模式。从 <expression> 返回的值必须是一个字符串。

表达式格式

['regex', <expression>, <expressionFormat>]

检查 <expression> 是否匹配由 <expressionFormat> 定义的特定模式。

<expression> 返回的值必须是一个字符串。

<expressionFormat> 返回的值必须是一个字符串。

示例

$expression = ['regex', ['get', 'name'], '/o/i'];

$evaluator = \ArekX\ArrayExpression\Evaluator::create();

$evaluator->run($expression, ['name' => 'John']); // returns true
值运算符

值运算符在 ArekX\ArrayExpression\Operators\ValueOperator 类中定义,用于返回一个静态值。

示例

$expression = ['value', 50];

$evaluator = \ArekX\ArrayExpression\Evaluator::create();

$evaluator->run($expression, ['name' => 'John']); // returns 50
获取运算符

获取运算符在 ArekX\ArrayExpression\Operators\GetOperator 类中定义,用于从键返回一个值。

示例

$expression = ['get', 'name'];

$evaluator = \ArekX\ArrayExpression\Evaluator::create();

$evaluator->run($expression, ['name' => 'John']); // returns 'John'
连接运算符

连接操作符定义在 ArekX\ArrayExpression\Operators\ConcatOperator 类中,用于连接两个或多个字符串。它要求评估结果为字符串。

示例

$expression = ['concat', ['get', 'first'], ['value', ' '], ['get', 'last']];

$evaluator = \ArekX\ArrayExpression\Evaluator::create();

$evaluator->run($expression, ['first' => 'John', 'last' => 'Snow']); // returns 'John Snow'

自定义操作符

您可以通过实现 Operator 接口并添加该操作符到您的 EvaluatorExpressionParser 中来手动创建自己的自定义操作符。

我们将实现一个自定义操作符,将所有 cat 单词的实例转换为 dog

我们想要实现的操作符定义是:['dog', <expression>]

首先我们实现一个 Operator

use ArekX\ArrayExpression\Interfaces\ExpressionParser;
use ArekX\ArrayExpression\Interfaces\Operator;
use ArekX\ArrayExpression\Interfaces\ValueParser;

class DogOperator implements Operator
{
    /** @var ExpressionParser */
    public $parser;

    /** @var string */
    public $name;

    /** @var Operator */
    public $subExpression;

    public function configure(array $config)
    {
        $this->name = $config[0];
        $this->assertIsExpression($config[1]); // Assert that the value is an expression.
        $this->subExpression = $this->parser->parse($config[1]);
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function setParser(ExpressionParser $parser)
    {
        $this->parser = $parser;
    }

    public function evaluate(ValueParser $value)
    {
        return str_ireplace('cat', 'dog', $this->subExpression->evaluate($value));
    }
}

创建此类后,我们需要将其添加到评估器的表达式解析器中,然后我们就可以设置了

$evaluator = \ArekX\ArrayExpression\Evaluator::create();
$evaluator->getExpressionParser()->setType('dog', DogOperator::class);

$test = ['dog', ['get', 'sentence']];

$result = $evaluator->run($test, ['sentence' => 'Hello this is cat.']); // Returns: Hello this is dog.

测试

运行 composer test 来运行测试。