llpo/mathepa

Mathepa 是一个用于评估 PHP 数学表达式的库

0.0.3 2019-01-31 18:13 UTC

This package is auto-updated.

Last update: 2024-09-14 19:20:24 UTC


README

Mathepa 是一个使用 PHP 语法解析数学表达式的解析器。

为什么?

这个想法源于将数学公式保存到数据库中以供以后在不同后端过程中使用的需要。

强烈建议在将公式保存到数据库或任何类型的存储之前,使用 Mathepa 作为安全约束和验证器,并且在检索后,始终作为代理操作以防止直接使用 eval

快速功能列表

  • 使用一行 PHP 语法表达数学表达式
  • 定义变量以参数化值
  • 支持三元运算符
  • 大多数常见的 数学函数 已列入白名单
  • 变量可以包含复杂的表达式并引用其他变量
  • eval 函数仅调用有效的表达式
  • 不需要外部依赖

它是如何工作的?

Mathepa 仅在表达式在语法和语法上有效且安全时使用 eval 函数。一个表达式只有在以下情况下才被认为是有效的

  • 语法有效,即所有标记都已识别。例如,“3.1.4”将无效
  • 语法有效,即文字不能紧挨着变量
  • 函数已被 列入白名单
  • 变量包含有效表达式
  • 未找到循环引用

注意 Mathepa 不会检查函数的形式参数数量。当参数数量不匹配时,执行将像在 PHP 控制台一样失败

> abs(-2, -3);
PHP Warning:  abs() expects exactly 1 parameter, 2 given in php shell code on line 1

在 Mathepa 中调用函数时,无论是参数数量不正确还是语法错误,都会始终抛出异常。在以下示例中 eval 被调用,因为没有无效的语法、语法或未知函数

(new Expression('cos()'))->evaluate();
(new Expression('cos(30, 60)'))->evaluate();

以下示例将由于语法错误而抛出异常。在以下情况下 eval 永远不会被调用

(new Expression('cos(30,)'))->evaluate();
(new Expression('3 2'))->evaluate();
(new Expression('abs(-43.24), 2'))->evaluate();
(new Expression('fakeMethod(22), 2'))->evaluate();

请参阅 单元测试以获取更多示例

示例

变量的使用

use \Mathepa\Expression;

$m = new Expression('1 / 2 * gravity * seconds');
$m->setVariable('gravity', '9.8');
$m->setVariable('seconds', '2');
$height = $m->evaluate();

函数的使用

use \Mathepa\Expression;

$m = new Expression();
$m->setVariable('distance', 40);
$m->setVariable('degrees', 35);
$height = $m->setExpression('distance * tan(degrees)')->evaluate();

复杂表达式

表达式中的三元运算符是允许的,但仅支持长语法,即 (expr1) ? (expr2) : (expr3)。

$m = new Expression('round((price - (price * discount)) * vat,  2) * units');
$m->setVariable('discount', '(units > 100 ? (units > 500 ? 0.10 : 0.20) : 0)');
$m->setVariable('price', 20);
$m->setVariable('units', 125);
$m->setVariable('vat', 1.19);
$total = $m->evaluate();

安装

composer require llpo/mathepa

使用 docker 的开发环境

安装开发包

docker-compose run install

打开一个 shell

docker-compose run shell

在容器中运行 composer 脚本

docker-compose run shell
composer test

直接调用 phpunit

docker-compose run shell
phpunit test/