Mało kto wie, ale w PHP też mamy metody call oraz bind, chociaż działają one tylko na closures (funkcje anonimowe), nie zaś na wszystkich callables. Zobaczmy w czym rzecz.

Ok, tworzymy closure, obiekt, bindujemy i używamy:

$sayHi = function(){
    return "I'm " . $this->name;
};

$john = (object) ['name' => "John", 'age' => 30];

$sayHiJohn = Closure::bind($sayHi, $john);

echo $sayHiJohn();
//I'm John

Zobaczmy na call:

class Person123 {
    public $age = 23;
}

$pers1 = new Person123();

$closure1 = function(){ 
    echo $this->age;
};
$closure1->call($pers1); //23

Call nam nie zadziała na obiekcie zrobionym z tablicy rzutowanej do object, ale na klasie już tak. Nawet na obiekcie z klasy anonimowej:

class Person123 {
    public $age = 23;
}

$pers1 = new Person123();

$closure1 = function(){ 
    echo $this->age;
};

$closure1->call($pers1); //23
$closure1->call(new class {
    public $age = 22;
}); //22

Jak widać bind to statyczna metoda klasy Closure (istnieje też Closure::fromCallable), natomiast call to metoda dostępna na każdym closure (tak jak w JS jest dostępna na każdej funkcji).

Podobna jest metoda bindTo:

$boundFunc = $closure1->bindTo($pers1);
$boundFunc(); //23

Mamy też funkcje (nie metody), które warto znać, czyli:

  • call_user_func
  • call_user_func_array
  • forward_static_call
  • forward_static_call_array

Natomiast jeżeli chodzi o bind, możemy sobie taki kod napisać:


function bindFunc($closure, $thisArg) {
          return $closure->bindTo($thisArg);
}

class Person {

    public $name;
    public $age;

    public function __construct($name, $age)
    {
        $this->name = $name;
        $this->age = $age;
    }
}

$person1 = new Person("John", 30);

$sayHiJohn = bindFunc(function(){
    return "Hi my name is " . $this->name . " and Im " .$this->age . " years old.";
}, $person1);

echo $sayHiJohn();
//Hi my name is John and Im 30 years old.