stillat / primitives
将原始值字符串解析成PHP数组。
Requires
Requires (Dev)
- phpunit/phpunit: ^8.5 || ^9.0
This package is auto-updated.
Last update: 2024-09-15 14:57:55 UTC
README
这个库提供了一种简单的方法,将简单值字符串转换为PHP运行时的等效值。
此库将解析以下类型的值
- 数字
- 字符串
- 数组
- 关联数组
- true, false, null
- 内置PHP常量
未知类型将返回它们的值为null
。
安装
可以使用composer安装此库
composer require stillat/primitives
示例用法
要使用此库,创建一个Parser
类的新实例,并调用parseString
方法
<?php use Stillat\Primitives\Parser; $parser = new Parser(); $result = $parser->parseString('[1, 2, 3], "some-string", "another", ["one" => 1, "two" => 2]');
将产生以下运行时结果
array(4) {
[0] =>
array(3) {
[0] =>
int(1)
[1] =>
int(2)
[2] =>
int(3)
}
[1] =>
string(11) "some-string"
[2] =>
string(7) "another"
[3] =>
array(2) {
'one' =>
int(1)
'two' =>
int(2)
}
}
此库还可以使用parseMethod
方法解析基本方法详情
<?php use Stillat\Primitives\Parser; $parser = new Parser(); $result = $parser->parseMethod('methodName([1, 2, 3])');
将产生以下运行时结果
array(2) {
[0] =>
string(10) "methodName"
[1] =>
array(1) {
[0] =>
array(3) {
[0] =>
int(1)
[1] =>
int(2)
[2] =>
int(3)
}
}
}
无效输入将产生一个null
值。
解析嵌套方法
parseMethod
的一个更高级的替代方法是parseMethods
方法
use Stillat\Primitives\Parser; $parser = new Parser(); $result = $parser->parseMethods("randomElements(['a', 'b', 'c', 'd', 'e'], rand(1, 5))");
检测到的方法调用将作为Stillat\Primitives\MethodCall
的实例返回。此类的每个实例将包含原始方法名称以及解析(和评估)后的运行时参数。parseMethods
将不会为您运行任何方法。
执行运行时方法
Primitives提供了一个名为MethodRunner
的实用工具类,可用于在任意目标类上执行parseMethods
的结果
<?php use Stillat\Primitives\Parser; use Stillat\Primitives\MethodRunner; $parser = new Parser(); $runner = new MethodRunner(); class MyClass { public function sayHello($name) { return 'Hello, '.$name; } } $myClassInstance = new MyClass(); $methods = $parser->parseMethods("sayHello('Dave')"); $result = $runner->run($methods, $myClassInstance);
执行上述代码后,$result
将包含值Hello, Dave
。
使用MethodRunner
时的重要注意事项
- 必须只有一个根方法调用
- 如果有多个根元素,则
run
方法返回null
MethodRunner
不会检查方法是否存在,允许调用__call
调用原生PHP函数
内部方法运行器不支持调用原生PHP函数。然而,我们可以创建一个实例,该实例可以(并利用适用于当前项目的逻辑来确定调用哪些函数是“安全”的)
<?php use Stillat\Primitives\Parser; use Stillat\Primitives\MethodRunner; $parser = new Parser(); $runner = new MethodRunner(); class Greeter { public function sayHello($name) { return 'Hello, '.$name; } } class MethodTarget { protected $instance; protected $safePhpFunctions = [ 'strtoupper' ]; public function __construct() { $this->instance = new Greeter(); } public function __call($name, $arguments) { // Replace with whatever logic makes sense. This approach // utilizes an allowed list of functions, but using // something like function_exists also works. if (in_array($name, $this->safePhpFunctions)) { return call_user_func($name, ...$arguments); } return call_user_func([$this->instance, $name], ...$arguments); } } $instance = new MethodTarget(); $result = $parser->parseMethods('sayHello(strtoupper("this is lowercase"))'); $methodResult = $runner->run($result, $instance);
执行上述代码后,$methodResult
将包含值Hello, THIS IS LOWERCASE
。这种方法之所以有效,是因为我们使用了PHP的__call
魔法方法进行方法重载。当我们尝试调用类实例上不存在的方法时,__call
方法将接收到方法名称和参数。如果安全函数列表包含传入的方法名称,我们将调用它并返回使用原始参数的结果。如果我们的安全列表不包含该函数,我们默认在目标类实例上调用它。
上下文变量
您还可以提供一个上下文数据数组,该数据可用于评估输入字符串。上下文变量使用$
语法。一旦评估,输入字符串中的变量名称将被它们的实际值替换
<?php use Stillat\Primitives\Parser; $parser = new Parser(); $context = [ 'name' => 'Dave', 'city' => 'Anywhere' ]; $result = $parser->parseString('[$name, $city]', $context);
执行前面的示例后,$result
将包含类似以下值
array(1) {
[0] =>
array(2) {
[0] =>
string(4) "Dave"
[1] =>
string(8) "Anywhere"
}
}
可以使用PHP的属性获取器语法(不支持数组访问器语法)利用嵌套变量路径
<?php use Stillat\Primitives\Parser; $parser = new Parser(); $context = [ 'nested' => [ 'arrays' => [ 'test' => [ 'name' => 'Dave', 'city' => 'Anywhere' ] ] ] ]; $result = $parser->parseString('[$nested->arrays->test->name,' . '$nested->arrays->test->city]', $context);
像之前一样,$result
变量将包含类似以下值
array(1) {
[0] =>
array(2) {
[0] =>
string(4) "Dave"
[1] =>
string(8) "Anywhere"
}
}
许可证
MIT许可证。请参阅LICENSE.MD文件