call_user_func_array的一个奇怪的问题。

问题已经被具体定义了,已经抽取成文件,文件下载链接。

https://pan.baidu.com/s/1jHYa0cQ

精简问题

我封装了一个类,这个类(A)有个方法(f)。
这个方法A::f中通过call_user_func_array函数调用了另一个类(B)对象(b_obj)的方法(f),实际参数通过在A::f()中调用func_get_args()给call_user_func_array。
可结果在B::f()中收到的参数被嵌套了,不明白的话,具体的情况见下面的事例代码来说吧。
大家可以把下面这段代码复制执行后,得到的结果是正确的结果。我现在的一个实际的问题注释中写了

//Example:
class B
{
   public function f($param1 = null)
   {
       var_dump($param1);
   }
}

class A
{
   private $obj = null;
   
   public function __construct()
   {
      $this->obj = new B();
   }

   public function f()
   {
      return call_user_func_array(array($this->obj,__FUNCTION__),func_get_args());
   }
}

$a_obj = new A();
$a_obj->f('name','zhangsan');
/**
 *=======问题说明========
 * 
//结果实际的情况输出是这样的,现在这里的代码为精简,我说明情况用的
array(2){
  0 => 'name',
  1 => 'zhangsan',
}
//本来这种正常情况是这样的
string('name');
======================*/

请问这是怎么一回事?有人遇到过么?上面精简的代码我测试过了结果会是正常的。我的显示情况是这种的精简版,我也一层层调试了,不得其解。(在具体的代码如下)

具体

    //first控制器中
   public function v()
    {

        $view = new \core\View();
        
        $view->assign('name','zhangsan');
    } 
    
    //second View中
    public function __call($method, $arguments)
    {
        /*
        dump(array(
            'method' => $method,
            'args' => $arguments));
        die();*/
        // TODO: Implement __call() method.
        if($this->instance &&
            method_exists($this->instance,$method)
        )
        {
            return call_user_func_array(array($this->instance,$method),$arguments);
        }
    }
    
    //third 最底层了
    public function assign($tpl_var, $value = null, $nocache = false)
    {
        
        dump(func_get_args());
        die();
        if (is_array($tpl_var)) {
            foreach ($tpl_var as $_key => $_val) {
                $this->assign($_key, $_val, $nocache);
            }
        } else {
            if ($tpl_var != '') {
                if ($this->_objType === 2) {
                    /** @var  Smarty_Internal_Template $this */
                    $this->_assignInScope($tpl_var, $value, $nocache);
                } else {
                    $this->tpl_vars[ $tpl_var ] = new Smarty_Variable($value, $nocache);
                }
            }
        }
        return $this;
    }
    
    //输出
    array(2) {
  [0] => string(4) "name"
  [1] => string(8) "zhangsan"
}
array(1) {
  [0] => array(2) {
    [0] => string(4) "name"
    [1] => string(8) "zhangsan"
  }
}
阅读 4.2k
5 个回答

func_get_args — 返回一个包含函数参数列表的数组,当然返回给你了一个数组

array(2){
  0 => 'name',
  1 => 'zhangsan',
}

而不是字符串 name

感觉是不是其它地方出问题了啊(最有可能是在某个地方参数被套了一层数组),因为模拟三层测试是正常的:

<?php
/**
 * 第一层
 */
class A
{
    private $obj = null;
    public function __construct()
    {
        $this->obj = new B();
    }
    public function assign($a, $b)
    {
        $this->obj->assign($a, $b);
    }
}
/**
 * 第二层
 */
class B
{
    private $obj = null;
    public function __construct()
    {
        $this->obj = new C();
    }
    public function __call($method, $arguments)
    {
        return call_user_func_array(array($this->obj,$method), $arguments);
    }
}

/**
 * 第三层
 */
class C
{
    public function assign($tpl_var, $value = null, $nocache = false)
    {
        var_dump(func_get_args());
    }
}
//测试
$a_obj = new A();
$a_obj->assign('name', 'zhangsan');

//输出
/* array(2) {
    [0]=>
    string(4) "name"
    [1]=>
    string(8) "zhangsan"
  } */

测试了你的Example代码,没发现这种情况。

下载了你的代码,首先先感叹一下吧,想不到竟然还有人在用Smarty,然后,你这个错误造成原因是Smarty的内部实现原理造成的,具体的代码我没深入的去看,我看Smarty里直接new一下竟然就能调用smarty_internal_data.php里的assign方法,太他妈神奇了,然后我看Smarty里有做include_once,然后再跟进,大致是Smarty.class.php的父类里有做实例化,跟进到这里我就没跟进了,建议你自己跟进一下。

你确定你的精简例子是好的?逗呢?

    test('a', 'b');

    public function test()
    {
        var_dump(func_get_args());
        call_user_func_array([$this, 'test2'], func_get_args());
    }

    public function test2($a)
    {
        var_dump($a);
    }

输出

array (size=2)
  0 => string 'a' (length=1)
  1 => string 'b' (length=1)

string 'a' (length=1)

对比一下,你就明白了,你的写法多传了一个无效参数

return call_user_func_array(array($this->obj,__FUNCTION__),func_get_args());
return call_user_func_array(array($this->obj,__FUNCTION__),[func_get_args()]);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题