Reputation: 221
I'm trying to pass a closure that uses object data without having to assign the object to a variable and passing it as a parameter to the closure, but I can't seem to figure out the right way to do it.
Here is my arbitrary class code:
class Person
{
var $__data = [];
function setData($key, $value)
{
$this->__data[$key] = $value;
return $this;
}
function setAutoData($map)
{
$this->__data = array_merge($this->__data, $map());
return $this;
}
function getData($key)
{
return $this->__data[$key];
}
}
This piece of code here will work and add the first_name to the data array:
$p = (new Person())->setData('full_name', 'Valerie Maddison Bricks');
print_r($p->setAutoData(function () use($p) {
return [
'first_name' => array_shift(explode(' ', $p->getData('full_name')))
];
}));
/*
Output:
Person Object
(
[__data] => Array
(
[full_name] => Valerie Maddison Bricks
[first_name] => Valerie
)
)
*/
This one doesn't work.
print_r((new Person())
->setData('full_name', 'Valerie Maddison Bricks')
->setAutoData(function () {
return [
'first_name' => array_shift(explode(' ', $this->getData('full_name'))),
];
}));
/*
Output:
Fatal error: Uncaught Error: Using $this when not in object context in C:\Damian\xampp\web\dbo-dev\teste.php:44
Stack trace:
#0 C:\Damian\xampp\web\dbo-dev\teste.php(22): {closure}()
#1 C:\Damian\xampp\web\dbo-dev\teste.php(46): Person->setAutoData(Object(Closure))
#2 {main}
thrown in C:\Damian\xampp\web\dbo-dev\teste.php on line 44
*/
Is there a way to achieve that in a similar way without relying on a variable?
Upvotes: 1
Views: 138
Reputation: 19764
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
)
)
Upvotes: 2