PHP如何动态传入参数

许多PHP框架能实现把URL中的数据,按照键值对动态解析传入方法的参数中。
例如:

//访问链接:“....../prints/a/123/b/456/”
/*对应function*/
function prints($a,$b)
{
    echo $a . $b;;
}
//最后输出'123456'

我刚开始想到的是利用可变参数,把URL数据解析成数组,作为可变参数传进去

//解析URL,过程省略
$func_name = ******;//方法名
$par_arr = [******];//将参数解析为关联数组
if (function_exists($func_name)) {
    $func_name(...$par_arr);
}

最后运行却得到报错,大致意思是不支持传入关联数组。也就是说,用可变参数的方法能实现参数按顺序传入,但不能按键值对传入。

然后我去翻了翻ThinkPHP,看了好久也没看出什么名堂。有没有哪位高手知道如何实现按照键值对动态传入参数,希望能给个Demo或者思路,非常感谢!

回复
阅读 7.8k
5 个回答
  • 首先需要说明的是,URL写作/index.php/xx/b/c可以直接被index.php文件接受,而不用做任何额外的操作

  • 但是如果需要在URL中隐藏index.php的话,才需要伪静态重写规则,将^(.*)$重写到/index.php/$1

  • 首先,需要从URI拆分键值对(此处省略)

  • 下面的思路是(依次):

    • 获取到要调用函数的参数名

    • 按照参数名称排序URI拆分出的键值对

    • 使用call_user_func_array()方法,动态调用函数

  • 由于键值对经过了按照参数名顺序排序,所以新的URI键值对中,值的顺序恰好是和需要调用函数的顺序对应的,所以可以直接用call_user_func_array()调用

  • 下面,介绍一下其中需要用到的知识:

    • call_user_func_array

    • array_fill_keys

    • ReflectionFunction或者ReflectionMethod

    • 由于Reflection部分缺少官方文档,贴出Overflow的回答作为示例:https://stackoverflow.com/que...

  • 下面上代码:

function test(....) {
}

...

$funcRef = new ReflectionFunction('test');
# 或者$funcRef = new ReflectionMethod('class', 'test');

$paramNames = [];

foreach($funcRef->getParameters() as $param) {
    $paramNames[] = $param->name;
}

$params = array_fill_keys($paramNames, NULL);
# 使用NULL为默认值,$paramNames为键名,填充一个参数键值对
# 如果参数对应项不传值,则那个值默认是NULL(暂不考虑有默认值的情况)

# 假设从URI获取的键值对生成的数组为$URIParam
# 将$URIParam中的值填入上面生成的参数数组中
# 遍历$params在$URIParam中找的原因是,如果遍历$URIParam,对应的$params中的值都是NULL,无法通过值确定键名是否存在
# 而遍历$params的话,键名一定是参数列表中的,只需要看在$URIParams中是否存在即可
foreach($params as $paramName => $param) {
    if(isset($URIParam[$paramName])) {
    # 使用isset是为了避免直接判断而产生的等效假值问题
    # 如果用if($URIParam[$paramName])无法区分0和''这种等效于假值的值
        $params[$paramName] = $param;
        # 由于,$params中的值已经定义过了,所以此处赋值并不会影响其顺序
    }
}

call_user_func('test', $params);
# 或者call_user_func_array([$class, 'method'], $params);

你参数传数组的话,还需要可变参数做什么?
参数就定义为一个数组就行了,你想往数组里放什么就放什么。

另外,这个问题与ThinkPHP没有什么关系。

直接传数组进去就好啦,没必要那么复杂,函数里设置一个数组用来枚举参数名,用foreach来遍历传进来的数组,做传参检查,没传进来的可以取默认值

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏