如果你一定要这样做的话,也不是不可以。
首先使用 debug_backtrace() 拿到调用栈,array_shift() 取出来,拿到文件,然后把文件交给 php-parser 找到调用的位置,就可以通过 php-parser 拿到了。<?php
require __DIR__ . '/vendor/autoload.php';
use PhpParser\ParserFactory;
/**
* 获取调用函数的参数
*
* @param array $backtrace debug_backtrace
* @param string $func 要查找的函数名字
*
* @return array 返回调用的参数,如果是变量,就返回变量名,如果不是变量是值,就返回序列号,从参数索引 0 开始编号
*/
function getCallFuncArgs(array $backtrace, string $func): array
{
// 获取调用栈中第一个
$caller = array_shift($backtrace);
// 取出文件
$file = $caller['file'];
// 创建解析器
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
$code = file_get_contents($file);
// 解析代码
$ast = $parser->parse($code);
$nodeFinder = new \PhpParser\NodeFinder();
// 查找所有的函数调用
$nodes = $nodeFinder->findInstanceOf($ast, \PhpParser\Node\Expr\FuncCall::class);
$argList = [];
foreach ($nodes as $node) {
// 找到函数名跟要查找的一致的
if (($node->name->parts[0] ?? null) === $func) {
// 创建索引值
$i = 0;
// 遍历所有参数
foreach ($node->args as $arg) {
// 如果是变量,就取变量名
if ($arg->value instanceof \PhpParser\Node\Expr\Variable) {
$argList[] = $arg->value->name;
} else {
// 否则就编号
$argList[] = '#' . $i;
}
$i++;
}
}
}
return $argList;
}
function testA()
{
// 调用
$keys = getCallFuncArgs(debug_backtrace(), __FUNCTION__);
// 填充一个关联数组,创建关系
$combine = array_combine($keys, func_get_args());
var_dump($combine);
}
$a = 1;
$b = 2;
$c = 2;
testA($a, $b, 1, 2, 3, 4, $c);
上面的代码输出就像这样:
当然,这只是实现的一种思路,如果要用到业务中,还是做好多方面的测试工作,以免出现意外情况。