PHP 5.4 - 'Closure $This Support'

PHP 5.4 - 'closure $this support'

This was already planned for PHP 5.3, but

For PHP 5.3 $this support for Closures was removed because no consensus could be reached how to implement it in a sane fashion. This RFC describes the possible roads that can be taken to implement it in the next PHP version.

It indeed means you can refer to the object instance (live demo)

<?php
class A {
private $value = 1;
public function getClosure()
{
return function() { return $this->value; };
}
}

$a = new A;
$fn = $a->getClosure();
echo $fn(); // 1

For a discussion, see the PHP Wiki

  • Closures: Object extension

and for historic interest:

  • closures (rfc)
  • removal-of-this (rfc:closures)

How to bind $this to a closure that is passed as a method parameter in PHP 5.4?

I actually didn't understand why using the bindTo method didn't work in this case, but I could get it to work using Closure::bind

public function get($callback) {
if (!is_callable($callback)) {
throw new InvalidArgumentException('Param must be callable.');
}

$bound = Closure::bind($callback, $this);
$bound();
}

Edit

Aparently the bindTo method has the same behavior, so you should reassign its return value to $callback. For example:

public function get($callback) {
if (!is_callable($callback)) {
throw new InvalidArgumentException('Param must be callable.');
}

$callback = $callback->bindTo($this);
$callback();
}

Can't access $this on PHP Closure passed to an object method

To avoid the use of $p, you can pass $this in the call of the closure. But you can't use $this in an anonymous function.

$this->__data = array_merge($this->__data, $map($this));

Then,

->setAutoData(function ($object) {
$array = explode(' ', $object->getData('full_name'));
return [
'first_name' => array_shift($array),
];
})

Note that array_shift requires a reference. You should create a variable for that.

Code:

class Person
{
private $__data = [];

public function setData($key, $value)
{
$this->__data[$key] = $value;
return $this;
}

public function setAutoData($map)
{
$this->__data = array_merge($this->__data, $map($this));
return $this;
}

public function getData($key)
{
return $this->__data[$key];
}

}

print_r(
(new Person())
->setData('full_name', 'Valerie Maddison Bricks')
->setAutoData(function ($object) {
$array = explode(' ', $object->getData('full_name'));
return [
'first_name' => array_shift($array),
];
})
);

Output:

Person Object
(
[__data:Person:private] => Array
(
[full_name] => Valerie Maddison Bricks
[first_name] => Valerie
)

)

Why can I not use $this as a lexical variable in PHP 5.5.4?

So it seems $this can be used simply if it isn't specified via the "use" keyword.

The following echoes 'bar':

class Foo
{
private $foo = 'bar';

public function bar()
{
return function()
{
echo $this->foo;
};
}
}

$bar = (new Foo)->bar();

$bar();

This was reported in the php-internals mailing list and is apparently overhang from 5.3's lack of support for this functionality:

http://marc.info/?l=php-internals&m=132592886711725

Scope Resolution: objects with closure calls

Its right on the man page for php anonymous functions:

Changelog

Version Description
5.4.0 $this can be used in anonymous functions.
5.3.0 Anonymous functions become available.

http://php.net/manual/en/functions.anonymous.php

Also

PHP 5.4 - 'closure $this support'

Is there a workaround for $this within a closure in PHP 5.3?

If info method is public you can do:

//...
public function fire()
{
$self = $this;
$self->info('Starting chunk');
Item::chunk(1000, function($items) use ($self)
{
foreach ($items as $item)
{
$self->info($item->img);
}
}
);

}
//...



If info is private you can't and you need to upgrade to php 5.4, because in PHP 5.3 the context in the closure is not the same of the object context.

Object context - Using $this in PHP 5.3 vs PHP 5.4

Correct. Views are rendered in a closure which is designed to act like a sandbox.

$this in a view should not work, but it looks like in PHP 5.4 it will pick up an object higher in the callstack, as it gives you Request, and not View or your controller. Which already indicates it's not reliable to use, as what $this represents will depend on the callstack.

Even if you don't use a templating engine, it is considered bad practice to use "logic" in your views, other than the logic needed to generate the HTML. Pass the data required to the view, either from the controller, or use a Viewmodel to prep the data.



Related Topics



Leave a reply



Submit