How to Bind `$this` to a PHP Function?

2019-09-20 17:23发布

问题:

As of JavaScript, we can do a thing like this to bind a scope to the desired function:

function myFunction() {
    alert(this.foo);
}

var MyClass = function() {
    this.foo = 1;
};

var c = new MyClass();
myFunction.call(c); // `1`

I want to do the same thing using PHP. Currently, what I see working successfully is like this, but this only applies to anonymous functions:

$my_function = function() {
    var_dump($this->foo);
};

class MyClass {
    public $foo = 1;
};

$c = new MyClass();
Closure::bind($my_function, $c)();

This does not work:

function my_function() {
    var_dump($this->foo);
}

class MyClass {
    public $foo = 1;
};

$c = new MyClass();
Closure::bind('my_function', $c)(); // :(
call_user_func([$c, 'my_function']); // :(

回答1:

If you're using PHP 7.1+, you can convert any PHP callable into a Closure using Closure::fromCallable (see PHP: Type hinting - Difference between `Closure` and `Callable` for some information about the difference):

$closure = Closure::fromCallable('my_function');

at which point you can bind your object instance to it and execute:

Closure::bind($closure, $c)();

See https://3v4l.org/aEnSI



回答2:

If you follow the docs, this becomes:

<?php
$my_function = function() {
  var_dump($this->foo);
};

class MyClass {
  public $foo = 1;
}

$c = new MyClass();
$f = Closure::bind($my_function, $c);
$f();


回答3:

You were close.

Using your code:

$my_function = function() {
     var_dump($this->foo);
};

class MyClass {
   public $foo = 1;
}

$c = new MyClass();

$bound =  Closure::bind($my_function, $c);

$bound();

But there is no need to use bind() static method. $my_function is already a callable, so you can do this directly:

$bound = $my_function->bindTo($c);
$bound()

You can see both versions working here.



标签: php oop closures