我有这部分代码:
class FTPClient
{
public function __construct() {
$args_num=func_num_args();
echo $args_num;
$this->{"__construct".($args_num===0 ? '' : $args_num)}(func_get_args());
}
function __call($name,$args) {
echo $name,count($args),'<br/>';
}
public function open() {
echo 'open';
}
}
$o = new FTPClient('127.0.0.1','user','pass');
$o = new FTPClient();
$o = new FTPClient('127.0.0.1','user');
$o->close();
输出如下:
3__construct31 01__construct11 //Don't understand how this output came together?! 2__construct21 close0
有人会这么善良并且可以向我解释这个输出的第二行吗?
答案 0 :(得分:5)
$o = new FTPClient('127.0.0.1','user','pass');
你有3个参数,意味着3用这一行打印:
$args_num = func_num_args(); echo $args_num; //output: 3
之后,您尝试调用方法__construct3()
:
$this->__construct3(func_get_args());
无法访问,意味着__call()
被调用。在该魔术方法中,您打印名称,此处为 __construct3
,参数计数(此处为参数数组)表示 1
。
输出:
3__construct31
$o = new FTPClient();
你有0个参数,意味着0用这一行打印:
$args_num = func_num_args(); echo $args_num; //output: 0
之后你试图调用方法__construct()
,构造函数:
$this->__construct(func_get_args());
构造函数是可调用的,因此{}不会调用__call()
。而是再次调用构造函数,但是使用一个包含参数数组的数组,这里是一个空数组。
现在在第二个电话中你有1个参数,意味着1用这一行打印:
$args_num = func_num_args(); echo $args_num; //output: 1
之后,您尝试调用方法__construct1()
:
$this->__construct1(func_get_args());
现在__construct1()
无法访问,意味着__call()
被触发。在这种魔术方法中,您可以打印名称,此处为 __construct1
,参数计数(此处为带参数数组的数组)表示 1
输出:
01__construct11
备注:强>
__call()
会被触发。答案 1 :(得分:2)
当您使用零参数运行构造函数时,将再次调用构造函数本身。由于构造函数是一个有效的方法,因此不会在那个时间调用__call(但稍后会在调用__construct1时调用)。
你看到01,因为第一次由构造函数打印0,然后调用__construct([empty array])
,打印1.然后调用__construct1,因为有一个参数(func_get_args的空数组) )) - 从而打印1__construct1(然后打印1)。
或许你的意思是将参数直接传递给构造函数而不是数组?
如果您打印出更多信息(例如正在进行打印的方法)以及在$args_num
之后打印换行符,您会发现这更有意义。那会让这个答案看起来更加混乱!
答案 2 :(得分:1)
你的第二行是:
$o = new FTPClient();
运行带有0个参数的__construct()
,从而打印0
。
然后,它生成一个要调用的函数名称:
"__construct".($args_num===0 ? '' : $args_num)
你运行了0参数的函数,所以这只是__construct
。由于此函数存在,因此它不会触发__call
函数。然后调用__construct
传递它func_get_args()
(返回一个空数组)。
然后__construct
再次运行 并带有1个参数(一个空数组),从而打印1
。
然后生成函数名__construct1
,调用后触发__call
。你调用__construct1
传递它func_get_args()
,这是一个包含一个元素的数组,是之前的空数组。
P.S。 count($args)
总是 1,因为您正在做:
$this->{"__construct".($args_num===0 ? '' : $args_num)}(func_get_args());
这会调用该函数并将其传递给一个参数。一个数组。
如果您想展开该数组并将每个元素作为自己的参数传递,那么您需要使用call_user_func_array
。
call_user_func_array([$this, "__construct".($args_num===0 ? '' : $args_num)], func_get_args());