In Javascript, you can control what object the this
keyword referes to by using apply
. In the following example, foo
will be called with this
equal to bar
:
function foo() { console.log(this); }
let bar = {};
foo.apply(bar);
Is there any way to achieve the same effect in PHP? Just creating a function referencing $this
outside of a class seems possible, but it is (unsurprisingly) just treated like any undefined variable.
I am aware of call_user_func_array
, but it does not let me assign to $this
. I am thinking reflection might be useful here, but I am not sure how.
As you could read in the comments, in PHP $this
refers to an object context and that could differs from JavaScript context.
However, talking about scope, you can work with closures that carriers an object scope. That scope, which is inside $this variable, can be changed using Closure::bindTo
or Closure::bind
.
Both of them have the intention to change the closure scope. It means to change the object inside $this
variable.
Here a simple example:
class Foo
{
private $number;
public function __construct($number)
{
$this->number = $number;
}
public function getClosure()
{
return function() {
echo $this->number;
};
}
}
And its use:
$foo = new Foo(10);
$closure = $foo->getClosure();
$closure();
Output:
10
The number 10 is the value from $number
private variable inside Foo
class from $foo
instance.
Changing the scope, we can obtain a different result while we access the same variable from other instance:
$foo = new Foo(10);
$foo2 = new Foo(50);
$closureFoo = $foo->getClosure();
$closureFoo();//First execution
echo ' and ';
$closureFoo2 = $closureFoo->bindTo($foo2);
$closureFoo2();//Second execution
Output:
10 and 50
If you want to use Closure::bind
, that's the code:
$closureFoo2 = Closure::bind($closureFoo , $foo2);
you can find more examples here: https://stackoverflow.com/a/40772588/1628790
Using the insights from other answers and comments, I came up with this implementation of apply
in PHP:
function apply($func, $new_this, ...$args) {
Closure::fromCallable($func)->bindTo($new_this)(...$args);
}
Not sure if this is useful in any way. However, it can be done. Note that this only works if $new_this
is an object, and not e.g. a string or number.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With