PHP-实现字符串表达式计算

什么是字符串表达式?即,将我们常见的表达式文本写到了字符串中,如:"$age >= 20",$age 的值是动态的整型变量。什么是字符串表达式计算?即,我们需要一段程序来执行动态的表达式,如给定一个含表达式的字符串变量并计算其结果,而表达式字符串是动态的,比如为客户A执行的表达式是 $orderCount >= 10,而为客户B执行的表达式是 $orderTotal >= 1000。 场景在哪儿?同一份程序具有完全通用性,但差异就其中一个表达式而已,那么我们需要将其抽象出来,让表达式变成动态的、可配置的、或可生成的。 方案一:eval 函数eval 函数可能是我们第一个想到的方案,也是最简单直接的方案。我们来试验下: $a = 10;var_dump(eval('return $a > 5;'));// 输出:// bool(true)嗯~完全能满足我们的需求,因为 eval 函数执行的 PHP 表达式,只要字符串内表达式符合 PHP 语法就行。 但需注意的是,eval 函数可执行任意 PHP 代码,也就意味着权限大、风险高、不安全。如果你的字符串表达式来自于外部输入,那务必注意了请自行做好安全检查和过滤,并考虑风险。当然,执行的是外部输入表达式,非常不建议使用此函数。 方案二:include 临时文件如何实现?将字符串表达式写入一个临时文件,然后 include 这个临时文件,执行完成后再删除这个临时文件。 方案依然很简单。需要考虑的有: 临时文件会很多,一个请求就有很多个,文件的过期和删除务必考虑在内文件的读写,也就牵扯到了磁盘 IO,那性能必定受到严重影响那这个方案我们还采用吗? 方案三:assert 断言其实 assert 做不到字符串表达式的计算,但提出来也算个猜想,因为能实现 PHP 表达式是否合法的校验。 下例演示了如何验证某个字符串表达式是否为合法的 PHP 表达式: try { assert('a +== 1');} catch (Throwable $e) { echo $e->getMessage(), "\n";}运行结果: Failure evaluating code: a +== 1可依然面临一个问题,那就是安全性,因为与 eval 一样能执行任意代码。所以,从 PHP 7.2 开始就不可以再执行字符串类型的表达式了。关于 PHP assert 断言,可参考 你所不知的 PHP 断言(assert) ...

September 8, 2019 · 2 min · jiezi

字节跳动开源Go结构体标签表达式解释器,成请求参数校验的杀手锏

go-tagexpr 是一个由字节跳动开源的 Golang 结构体标签表达式解释器。它主要应用于各种场景的请求参数校验,且性能高效,成为参数校验的杀手锏。主要特性:支持各种常用运算符支持访问数组、切片、字典的成员支持访问当前结构中任意字段支持访问嵌套字段、非导出字段等内置 len、sprintf、regexp 函数支持单表达式与多表达式两种定义模式提供了参数校验子包看一个参数校验的小例子:package validator_testimport ( “fmt” “github.com/bytedance/go-tagexpr/validator”)func Example() { var vd = validator.New(“vd”) type InfoRequest struct { Name string vd:"($!='Alice'||(Age)$==18) && regexp('\\w')" Age int vd:"$>0" } info := &InfoRequest{Name: “Alice”, Age: 18} fmt.Println(vd.Validate(info) == nil) // Output: // true}更多语法详情,请转到Github源码仓库:https://github.com/bytedance/…

January 30, 2019 · 1 min · jiezi