Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way NOT to capture $this in a PHP anonymous function?

I have a PHP code that looks like this:

class A {
    public function __construct() {
        $this->b = new B(function($x) { return $x + 1; });
    }
};

class B {
    public function __construct($dataProcessingFunction) {
        $this->dataProcessingFunction = $dataProcessingFunction;
    }

    public function processData($data) {
        $f = $this->dataProcessingFunction;
        return $f($data);
    }
};

But there is a problem: I absolutely need B's destructor to be called before A's destructor. This seems reasonable as you can see. The B object doesn't need any A, so there should be no problem.

But since PHP 5.4.0, closures seem to automatically capture implicitly $this. Therefore, the lambda function that I pass to B and that is stored by B contains a reference to A.

Which means that A contains a pointer to B, and B contains a pointer to A (through the closure). In this kind of situation, the PHP documentation says that destructors are only called on garbage collection and in a random order. And guess what: B's destructor is always called before A's.

Is there a way to solve this in a elegant way?

like image 720
Tomaka17 Avatar asked Dec 12 '12 20:12

Tomaka17


People also ask

Which statement is not allowed in anonymous function?

Which statement is not allowed in anonymous function? As of PHP 7.1, these variables must not include superglobals, $this , or variables with the same name as a parameter. A return type declaration of the function has to be placed after the use clause.

Are anonymous functions closures?

Anonymous functions, also known as closures , allow the creation of functions which have no specified name. They are most useful as the value of callable parameters, but they have many other uses. Anonymous functions are implemented using the Closure class.

How can you pass a local variable to an anonymous function in PHP?

Yes, use a closure: functionName($someArgument, function() use(&$variable) { $variable = "something"; }); Note that in order for you to be able to modify $variable and retrieve the modified value outside of the scope of the anonymous function, it must be referenced in the closure using & . It's new!

What is the point of anonymous functions?

The advantage of an anonymous function is that it does not have to be stored in a separate file. This can greatly simplify programs, as often calculations are very simple and the use of anonymous functions reduces the number of code files necessary for a program.


1 Answers

Thanks to Explosion Pills, I've found the solution in the Closure class.

You can in fact change the $this stored inside the closure, like this:

$cb = function($x) { return $x + 1; };
$cb = $cb->bindTo(null);

// now $cb doesn't contain a pointer to $this anymore

Note that you can't do this, or you'll get a syntax error:

// syntax error
$cb = (function($x) { return $x + 1; })->bindTo(null);
like image 78
Tomaka17 Avatar answered Sep 27 '22 19:09

Tomaka17