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