okvpn/expression-language

基于twig语法的快速强大的PHP表达式语言

1.0.3 2024-09-14 11:34 UTC

This package is auto-updated.

Last update: 2024-09-14 12:42:34 UTC


README

此库提供了安全评估表达式的接口,并将它们编译为原生PHP代码以提高性能。

Tests Latest Stable Version PHP Version Require

用途

它是Symfony Expression Language的一个替代品,允许更多的操作,如forif等。您可以实现任何逻辑并安全快速地执行它。我们从TWIG AST树中移除了PRINT_TOKENTEXT_TOKEN以防止输出,添加了return语句,并进行了更多改进。

特性

  • 允许执行脚本和评估表达式。
  • 使用PhpStorm twig调试器功能进行调试。
  • 支持所有twig特性,如sandbox、自定义扩展、标记、函数。
  • 最小性能开销 - 比twig更快。
  • 语法高亮已经集成到最流行的IDE中。

示例用法

基本评估示例

$lang = new TwigLanguage(options: ['cache' => __DIR__ . '/var/cache/twig']);
$context = ['var1' => 10, 'users' => [1, 2, 5], 'user' => 1];

$lang->evaluate('user in users ? users|length + 1 : var1')

执行脚本

{% set msg = 'New sms' %}
{% set newUsers = '' %}
{% set usersList = [] %}
{% set lastUserId = redis_get('sms-user') %} # redis_get - custom function

{% for user in users %}
    {% if user > lastUserId %}
        {% set newUsers = newUsers ~ user ~ ' ' %}
        {% do redis_set('sms-user', user, 0) %}
        {% set usersList[_key] = user %} # allow set to array 
    {% endif %}
{% endfor %}

{% if newUsers is not empty %}
    {% do telegram_send('chart111', msg ~ "\n" ~ newUsers|trim) %} # telegram_send - custom function
{% endif %}

{% return usersList %} # new return token 
$lang = new TwigLanguage();
$script = <<<TXT
...
{% return 10 + 15 %}
TXT;

var_dump($lang->execute($script, $context));

// execute with template 
$loader = new \Twig\Loader\FilesystemLoader(__DIR__ . '/scripts');
$lang = new TwigLanguage(loader: $loader);
var_dump($lang->execute('test22.twig', $context));

evaluate 方法 - 比使用 execute 更快,因为我们跳过了额外的异常处理和错误逻辑。此外,evaluate 可以接受没有 {% 标记的代码。

基准测试

我们使用以下测试来比较Symfony Expression Language和此库之间的开销

$lang = new TwigLanguage(options: [
    'cache' => __DIR__ . '/var/cache/twig',
    'auto_reload' => true,
]);


$expr = 'user == 1 ? var1 + var2 : var1 + 1';
$lang->evaluate($expr, $context);

// Symfony EL 
$sf = new ExpressionLanguage();
$expression = $sf->parse($expr, array_keys($context));
$sf->evaluate($expression, $context);

// Native PHP

$fn = static function ($context) {
    return $context['user'] === 1 ? $context['var1'] + $context['var2'] : $context['var1'] + 1;
};

$t1 = microtime(true);
for ($i = 0; $i < 200000; $i++) {
    // comment line where needed
    $result = $fn($context);
    $result = $sf->evaluate($expression, $context);
    $result = $lang->evaluate($expr, $context);
}

echo (microtime(true) - $t1)/200000 * 1000000 . "\n";

扩展和sandbox模式。

Twig文档

结果

许可证

MIT许可证。