__call() 方法解释
__call() method explanation
我有这部分代码:
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
有好心人可以解释一下这个输出的第二行吗?
当您 运行 使用零参数构造函数时,将再次调用构造函数本身。由于构造函数是一个有效的方法,__call 不会在那个时候被调用(但稍后会在您调用 __construct1 时)。
你看到 01 是因为构造函数第一次打印 0,然后调用 __construct([empty array])
,打印 1。然后调用 __construct1 因为有一个参数 ( func_get_args()) 的空数组 - 因此打印 1__construct1 (然后打印 1).
也许您的意思是将参数直接传递给构造函数,而不是在数组中?
如果您打印出更多信息(例如打印的方法)并在 $args_num
之后打印换行符,您会发现这更有意义。这会让这个答案看起来不那么令人困惑!
你的第二行是:
$o = new FTPClient();
使用 0 个参数运行 __construct()
,因此打印 0
。
然后,它生成一个函数名来调用:
"__construct".($args_num===0 ? '' : $args_num)
你 运行 参数为 0 的函数,所以这就变成了 __construct
。由于此函数 存在 ,因此不会触发 __call
函数。然后你调用 __construct
传递它 func_get_args()
(returns 你是一个空数组)。
然后 __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());
第一个例子
$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()
在您尝试调用无法访问的方法时被触发。
我有这部分代码:
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
有好心人可以解释一下这个输出的第二行吗?
当您 运行 使用零参数构造函数时,将再次调用构造函数本身。由于构造函数是一个有效的方法,__call 不会在那个时候被调用(但稍后会在您调用 __construct1 时)。
你看到 01 是因为构造函数第一次打印 0,然后调用 __construct([empty array])
,打印 1。然后调用 __construct1 因为有一个参数 ( func_get_args()) 的空数组 - 因此打印 1__construct1 (然后打印 1).
也许您的意思是将参数直接传递给构造函数,而不是在数组中?
如果您打印出更多信息(例如打印的方法)并在 $args_num
之后打印换行符,您会发现这更有意义。这会让这个答案看起来不那么令人困惑!
你的第二行是:
$o = new FTPClient();
使用 0 个参数运行 __construct()
,因此打印 0
。
然后,它生成一个函数名来调用:
"__construct".($args_num===0 ? '' : $args_num)
你 运行 参数为 0 的函数,所以这就变成了 __construct
。由于此函数 存在 ,因此不会触发 __call
函数。然后你调用 __construct
传递它 func_get_args()
(returns 你是一个空数组)。
然后 __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());
第一个例子
$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()
在您尝试调用无法访问的方法时被触发。