0

0

如何安全地在PHP中执行动态表达式?Leongrdic/smplang助你构建灵活的规则引擎!

碧海醫心

碧海醫心

发布时间:2025-11-12 15:05:26

|

1028人浏览过

|

来源于php中文网

原创

如何安全地在php中执行动态表达式?leongrdic/smplang助你构建灵活的规则引擎!

可以通过一下地址学习composer学习地址

告别 eval() 的噩梦:PHP 动态表达式的安全之道

作为PHP开发者,你是否曾遇到这样的场景:需要根据用户的输入或者系统配置,动态地执行一段逻辑或计算一个值?例如,一个复杂的定价规则引擎,一个用户自定义的报表筛选条件,或者一个灵活的权限判断表达式。

最直接的解决方案,可能很多人会想到PHP原生的 eval() 函数。它确实能将字符串作为PHP代码执行,听起来很方便。然而,一旦你开始考虑安全性,eval() 就会立刻变成一个令人头疼的潘多拉魔盒。

eval() 的陷阱与我们面临的挑战

使用 eval() 的最大风险在于代码注入。如果用户输入或外部数据未经严格过滤就传入 eval(),攻击者可以轻易地执行任意PHP代码,从而导致数据泄露、系统破坏甚至服务器被完全控制。这就像在你的应用中埋下了一颗定时炸弹,随时可能引爆。

为了避免这种风险,我们不得不投入大量精力去编写复杂的过滤和验证逻辑,但这不仅耗时耗力,而且稍有疏忽就可能留下安全漏洞。而如果选择自己从头实现一个表达式解析器和求值器,那更是一项浩大的工程,需要深入理解词法分析、语法分析和抽象语法树(AST)等概念,对于大多数业务开发来说,这显然是不切实际的。

立即学习PHP免费学习笔记(深入)”;

面对这种既要灵活又要安全的矛盾,我们急需一个既能安全地执行动态表达式,又能保持开发效率的工具

leongrdic/smplang:PHP 动态表达式的沙盒利器

幸运的是,leongrdic/smplang 这个 Composer 包为我们带来了曙光。它是一个用PHP编写的简单表达式语言,能够在不使用 eval() 的情况下评估表达式。你可以把它想象成一个安全的、拥有自己语法的 eval() 替代品,它在一个“沙盒”环境中运行,只允许访问你明确传入的变量、函数或闭包。

leongrdic/smplang 的设计灵感来源于 Symfony Expression Language,但在某些方面提供了更灵活的特性,例如:

  • 数组解包(Array Unpacking):在数组或函数调用中方便地展开其他数组。
  • 命名参数(Named Arguments):让函数调用更具可读性。
  • 更简单的函数定义:直接传入PHP闭包或可调用对象。

这使得 leongrdic/smplang 在许多场景下成为一个非常实用的选择。

如何开始使用 leongrdic/smplang

首先,通过 Composer 轻松安装它:

composer require leongrdic/smplang

接下来,让我们看看如何使用它来评估表达式。

Ideogram
Ideogram

Ideogram是一个全新的文本转图像AI绘画生成平台,擅长于生成带有文本的图像,如LOGO上的字母、数字等。

下载

1. 基本用法

创建一个 \Le\SMPLang\SMPLang 实例,并可以选择性地传入一个关联数组,作为表达式中可用的全局变量:

 'Alice',
    'age' => 30,
    'is_admin' => true,
]);

// 评估一个简单的表达式
$result = $smpl->evaluate('username ~ " is " ~ age ~ " years old."');
echo "Result 1: " . $result . PHP_EOL; // 输出:Result 1: Alice is 30 years old.

// 评估一个条件表达式
$accessGranted = $smpl->evaluate('is_admin && age >= 18');
echo "Result 2: " . ($accessGranted ? 'Access Granted' : 'Access Denied') . PHP_EOL; // 输出:Result 2: Access Granted

你也可以在调用 evaluate() 方法时,传入第二个参数来提供临时的局部变量。这些局部变量会覆盖构造函数中传入的同名变量,且只在当前表达式中有效:

 'Alice',
]);

$result = $smpl->evaluate('username == localUser ? "Same" : "Different"', [
    'localUser' => 'Bob',
]);
echo "Result 3: " . $result . PHP_EOL; // 输出:Result 3: Different

如果表达式中引用的变量未定义,\Le\SMPLang\Exception 异常将被抛出,这有助于你及时发现问题。

2. 核心语法特性一览

leongrdic/smplang 提供了直观且功能丰富的表达式语法:

  • 支持的字面量null, true, false, 字符串("string", 'string', string), 数字(1, 1.2, -1), 数组([1, 'foo'], ["key": 'value']), 对象({foo: "bar"})。
  • 数组操作
    • 定义:[element1, element2]["key": element, string_variable: element2]
    • 数组解包[element1, ...arrayVar, ...arrayVar2]
    • 访问:array.key.0array['key'][0] (支持动态键)。
  • 对象操作
    • 定义:{foo: "bar", baz: 23} (也支持数组解包)。
    • 属性访问:object.property
    • 方法调用:object.method(parameters)
  • 函数/闭包调用
    • 直接调用:closure_var(param1, param2)
    • 命名参数foo(search: value, count: 1)
    • 支持数组解包:bar(param1, ...array, ...array2)
  • 丰富的运算符
    • 算术:+, -, *, /, %, ** (幂)。
    • 比较:===, !==, ==, !=, >, , >=, .
    • 逻辑:&&, ||, !.
    • 字符串连接:~
  • 三元表达式a ? b : c, a ?: b, a ? b

示例:使用函数和复杂逻辑

 fn(string $name): string => "Hello, " . $name,
    'multiply' => fn($a, $b) => $a * $b,
    'data' => ['items' => [10, 20, 30], 'user' => ['name' => 'Charlie']],
]);

// 调用自定义闭包,使用数组访问和字符串连接
$result1 = $smpl->evaluate('greeting(data.user.name) ~ "! Your first item is " ~ data.items[0]');
echo "Result 4: " . $result1 . PHP_EOL; // 输出:Result 4: Hello, Charlie! Your first item is 10

// 使用命名参数和算术运算
$result2 = $smpl->evaluate('multiply(a: 5, b: 10) + data.items[2]');
echo "Result 5: " . $result2 . PHP_EOL; // 输出:Result 5: 80

// 数组解包示例
$result3 = $smpl->evaluate('[1, ...data.items, 40]');
echo "Result 6: ";
print_r($result3); // 输出:Result 6: Array ( [0] => 1 [1] => 10 [2] => 20 [3] => 30 [4] => 40 )

leongrdic/smplang 的优势与实际应用效果

  1. 绝对安全:这是 leongrdic/smplang 最核心的优势。它完全避免了 eval() 的使用,提供了一个安全的沙盒环境,你无需担心恶意代码注入的风险。
  2. 高度灵活:你可以将任何PHP变量、对象实例、甚至闭包作为表达式的上下文传入。这意味着你可以轻松地在表达式中调用自定义的业务逻辑。
  3. 语法简洁强大:借鉴了PHP和JavaScript的一些优点,其语法直观易懂,同时支持数组解包、命名参数等高级特性,使得复杂逻辑的表达变得非常优雅。
  4. 性能可接受:虽然它不像原生PHP代码那样快,但对于大多数动态规则评估的场景,其性能是完全可以接受的,并且比自己实现一个解析器要高效得多。

实际应用场景包括但不限于:

  • 自定义规则引擎:为你的业务逻辑(如折扣计算、用户权限判断、工作流条件)提供一个灵活且安全的配置方式,让非技术人员也能通过简单的表达式来调整业务规则。
  • 动态配置管理:根据不同的环境或用户角色,动态评估配置项的值。
  • 用户自定义计算器:允许用户输入简单的数学或逻辑表达式进行计算,而无需担心安全问题。
  • 轻量级模板逻辑:在某些不需要完整模板引擎的场景下,用于渲染简单的动态内容。

总结

告别 eval() 带来的安全焦虑,leongrdic/smplang 为PHP开发者提供了一个强大、安全且易于使用的动态表达式评估解决方案。无论你是要构建复杂的规则引擎,还是仅仅需要一个安全的替代方案来处理动态逻辑,leongrdic/smplang 都将是你的得力助手。它不仅提升了开发效率,更重要的是,为你的应用程序带来了更高的安全性。快去尝试一下,让你的PHP应用变得更加灵活和健壮吧!

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2404

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1551

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1449

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

951

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1414

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1233

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1445

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1305

2023.11.13

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

80

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
第二十四期_PHP8编程
第二十四期_PHP8编程

共86课时 | 3.4万人学习

成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 2.4万人学习

第二十三期_PHP编程
第二十三期_PHP编程

共93课时 | 6.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号