Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using `$this` in an anonymous function in PHP pre 5.4.0

The PHP manual states

It is not possible to use $this from anonymous function before PHP 5.4.0

on the anonymous functions page. But I have found I can make it work by assigning $this to a variable and passing the variable to a use statement at the function definition.

$CI = $this;
$callback = function () use ($CI) {
    $CI->public_method();
};

Is this a good practice?
Is there a better way to access $this inside an anonymous function using PHP 5.3?

like image 785
steampowered Avatar asked Dec 05 '11 20:12

steampowered


People also ask

What is use in anonymous functions PHP?

Anonymous function is a function without any user defined name. Such a function is also called closure or lambda function. Sometimes, you may want a function for one time use. Closure is an anonymous function which closes over the environment in which it is defined. You need to specify use keyword in it.

How do you declare an anonymous function?

An anonymous function can also have multiple arguments, but only one expression. We may also declare anonymous function using arrow function technique which is shown below: ( () => { // Function Body... } )

Which function is known as anonymous function give example?

An anonymous function is a function that was declared without any named identifier to refer to it. As such, an anonymous function is usually not accessible after its initial creation. Normal function definition: function hello() { alert('Hello world'); } hello();

When would you use an anonymous function?

Anonymous functions are often arguments being passed to higher-order functions, or used for constructing the result of a higher-order function that needs to return a function. If the function is only used once, or a limited number of times, an anonymous function may be syntactically lighter than using a named function.


3 Answers

It will fail when you try to call a protected or private method on it, because using it that way counts as calling from the outside. There is no way to work around this in 5.3 as far as I know, but come PHP 5.4, it will work as expected, out of the box:

class Hello {      private $message = "Hello world\n";      public function createClosure() {         return function() {             echo $this->message;         };     }  } $hello = new Hello(); $helloPrinter = $hello->createClosure(); $helloPrinter(); // outputs "Hello world" 

Even more, you will be able to change what $this points to at runtime, for anonymus functions (closure rebinding):

class Hello {      private $message = "Hello world\n";      public function createClosure() {         return function() {             echo $this->message;         };     }  }  class Bye {      private $message = "Bye world\n";  }  $hello = new Hello(); $helloPrinter = $hello->createClosure();  $bye = new Bye(); $byePrinter = $helloPrinter->bindTo($bye, $bye); $byePrinter(); // outputs "Bye world" 

Effectively, anonymus functions will have a bindTo() method, where the first parameter can be used to specify what $this points to, and the second parameter controls what should the visibility level be. If you omit the second parameter, the visibility will be like calling from the "outside", eg. only public properties can be accessed. Also make note of the way bindTo works, it does not modify the original function, it returns a new one.

like image 93
K. Norbert Avatar answered Sep 29 '22 16:09

K. Norbert


Don't always rely on PHP to pass objects by reference, when you are assigning a reference itself, the behavior is not the same as in most OO languages where the original pointer is modified.

your example:

$CI = $this;
$callback = function () use ($CI) {
$CI->public_method();
};

should be:

$CI = $this;
$callback = function () use (&$CI) {
$CI->public_method();
};

NOTE THE REFERENCE "&" and $CI should be assigned after final calls on it has been done, again else you might have unpredictable output, in PHP accessing a reference is not always the same as accessing the original class - if that makes sense.

http://php.net/manual/en/language.references.pass.php

like image 23
Christof Coetzee Avatar answered Sep 29 '22 16:09

Christof Coetzee


That is the normal way it was done.
b.t.w, try to remove the & it should work without this, as objects pass by ref any way.

like image 34
Itay Moav -Malimovka Avatar answered Sep 29 '22 16:09

Itay Moav -Malimovka