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.