在Javascript中,我可以将this
绑定到另一个函数,并使用.call
或.apply
调用它
在 PHP 中,我可以用 call_user_func
或 call_user_func_array
来做到这一点,但是如何将$this
绑定到函数中呢?
Javascript:
function greet() {
alert('Hello ' + this.name);
}
function SomeClass() {}
SomeClass.prototype = {
name: 'John',
test: function() {
greet.call(this);
}
}
var me = new SomeClass();
me.test(); // Hello John
.PHP:
function greet() {
echo 'Hello ' . $this->name;
}
class SomeClass {
public $name = 'John';
function test() {
call_user_func('greet');
}
}
$me = new SomeClass;
$me->test(); // Fatal error: Using $this when not in object context
更新:
感谢@deceze Reflection
的想法,我找到了这些解决方案,但我认为这对性能不利(x10 比直接调用慢(,但在阅读时很清楚。
我写了两个函数:
// See also Javascript: Function.prototype.apply()
function function_apply($fn, $thisArg, $argsArray = array()) {
static $registry;
if (is_string($fn)) {
if (!isset($registry[$fn])) {
$ref = new 'ReflectionFunction($fn);
$registry[$fn] = $ref->getClosure();
}
$fn = $registry[$fn];
}
return call_user_func_array($fn->bindTo($thisArg), $argsArray);
}
// See also Javascript: Function.prototype.call()
function function_call($fn, $thisArg /*, arg1, arg2 ... */) {
return function_apply($fn, $thisArg, array_slice(func_get_args(), 2));
}
并将call_user_func
替换为function_call
:
function greet() {
echo 'Hello ' . $this->name;
}
class SomeClass {
public $name = 'John';
function test() {
function_call('greet', $this);
}
}
$me = new SomeClass;
$me->test(); // Hello John
PHP不是JavaScript:你不能自由地混合在类内部和外部定义的函数,在调用它们时切换它们的上下文。任何尝试使用$this
您描述的方式都将导致致命错误:Using $this when not in object context
。
再说一次,对于无类函数,一个简单的约定可以实现同样的效果:传递它们应该使用的上下文作为它们的第一个参数。显然,你只能使用上下文对象的公共接口 - 但话又说回来,它与JavaScript相同。另外,作为奖励,您将能够通过类提示进行类型检查。例如:
function greet(SomeClass $_this) {
echo 'Hello ' . $_this->name;
}
class SomeClass {
public $name = 'John';
function test() {
call_user_func('greet', $this);
}
}
$me = new SomeClass;
$me->test(); // Hello John
你可以使用 Closure::bind 函数
<?php
class AAA {
public function ccc()
{
$bbb = new BBB;
$r = $bbb->abc()[0];
var_dump($r, Closure::bind($r, $this));
}
}
class BBB {
public function abc()
{
return [function () {
}];
}
}
$aaa = new AAA;
$aaa->ccc();
和结果
object(Closure)#3 (1) {
["this"]=>
object(BBB)#2 (0) {
}
}
object(Closure)#4 (1) {
["this"]=>
object(AAA)#1 (0) {
}
}