PHP equivalent of JavaScript binding

Sorry my english first. I am not a native speaker and it is a pity if he looks rude, this is the first time I publish on this site. I think my problem is pretty simple. Say we have:

class A { function foo() { function bar ($arg){ echo $this->baz, $arg; } bar("world !"); } protected $baz = "Hello "; } $qux = new A; $qux->foo(); 

In this example, "$ this" obviously does not apply to my "$ qux" object.

How do I do to make this "$ qux"?

Like JavaScript: bar.bind(this, "world !")

+3
source share
4 answers

PHP has no nested functions, so in your example bar is essentially global. You can achieve what you want by using closure (= anonymous functions) that support binding with PHP 5.4:

 class A { function foo() { $bar = function($arg) { echo $this->baz, $arg; }; $bar->bindTo($this); $bar("world !"); } protected $baz = "Hello "; } $qux = new A; $qux->foo(); 

UPD: however, bindTo($this) doesn't make much sense because closing will automatically inherit this from the context (again, in 5.4). So your example could be simple:

  function foo() { $bar = function($arg) { echo $this->baz, $arg; }; $bar("world !"); } 

UPD2: for php 5.3 - this seems possible only with an ugly hack:

 class A { function foo() { $me = (object) get_object_vars($this); $bar = function($arg) use($me) { echo $me->baz, $arg; }; $bar("world !"); } protected $baz = "Hello "; } 

Here get_object_vars() used to β€œpublish” protected / private properties to make them available within the closure.

+3
source

Actually, $this refers to $qux when called in this context.

You cannot use $this in a context other than the method of the object, so if you did something like this:

 function test() { echo $this->baz; } 

This will not work no matter what you do.

+2
source

for him, this is a little strange, but if you use a function inside a function, then, of course, some closing devices work. you may have a similar problem in javascript. I would suggest not using them at all, but if for some reason you do not want it, then I would try it like this (not tested):

 class A { function foo() { $that = $this; function bar ($arg){ echo $that->baz, $arg; } bar("world !"); } protected $baz = "Hello "; } $qux = new A; $qux->foo(); 

UPDATE if the nested function acts like a global function, then you can pass your object as a parameter if you need to use it:

Foo () function {

  function bar ($o,$arg){ echo $o->baz, $arg; } bar($this,"world !"); } 
0
source

If I understand what you are trying to achieve, it could be like this:

 <?php class Foo { public $prop; public function __construct($prop) { $this->prop = $prop; } public function __call($name, $arguments) { if (!isset($this->$name)) { throw new InvalidArgumentException("No such property: $name"); } if (! $this->{$name} instanceof Closure) { throw new InvalidArgumentException("{$name} is not a closure"); } $c = $this->{$name}->bindTo($this); return $c(...$arguments); } } $f = new Foo("bar"); $f->bar = function ($arg) { print_r([$arg, $this->prop]); }; $f->bar("A"); ?> 

That way, you can essentially disable any function in the class and call it as if it were local, even including the use of $this . However, there are two limitations:

  • this seems pointless since traits are available, unless you add really dynamically defined ones in an unmodifiable package
  • although a closure can access properties on $this , it is still external to the object, so it can only access public properties. Attempting to access protected / private properties will fail.
0
source

Source: https://habr.com/ru/post/1209645/


All Articles