Closure#bind()
method.Closure#bind()
basically allows you to get an instance of a closure with the scope of a given class or object. Gracefully! This is how you can add API to existing objects!Kitchen#yummy
private property: <?php class Kitchen { private $yummy = 'cake'; }
<?php $sweetsThief = function (Kitchen $kitchen) { return $kitchen->yummy; }
yummy
from the Kitchen
instance: <?php $kitchen = new Kitchen(); var_dump($sweetsThief($kitchen));
$sweetsThief
: Fatal error: Cannot access private property Kitchen::$yummy in [...] on line [...]
Closure#bind()
: <?php $kitchen = new Kitchen(); // Closure::bind() $sweetsThief = Closure::bind($sweetsThief, null, $kitchen); var_dump($sweetsThief($kitchen));
<?php for ($i = 0; $i < 100000; $i += 1) { $sweetsThief = Closure::bind(function (Kitchen $kitchen) { return $kitchen->yummy; }, null, 'Kitchen'); } <?php for ($i = 0; $i < 100000; $i += 1) { $sweetsThief = new ReflectionProperty('Kitchen', 'yummy'); $sweetsThief->setAccessible(true); }
<?php $kitchen = new Kitchen(); $sweetsThief = Closure::bind(function (Kitchen $kitchen) { return $kitchen->yummy; }, null, 'Kitchen'); for ($i = 0; $i < 100000; $i += 1) { $sweetsThief($kitchen); } <?php $kitchen = new Kitchen(); $sweetsThief = new ReflectionProperty('Kitchen', 'yummy'); $sweetsThief->setAccessible(true); for ($i = 0; $i < 100000; $i += 1) { $sweetsThief->getValue($kitchen); }
<?php $sweetsThief = Closure::bind(function & (Kitchen $kitchen) { return $kitchen->yummy; }, null, $kitchen); $cake = & $sweetsThief($kitchen); $cake = 'lie'; var_dump('the cake is a ' . $sweetsThief($kitchen));
<?php $reader = function & ($object, $property) { $value = & Closure::bind(function & () use ($property) { return $this->$property; }, $object, $object)->__invoke(); return $value; }; $kitchen = new Kitchen(); $cake = & $reader($kitchen, 'cake'); $cake = 'sorry, I ate it!'; var_dump($kitchen);
Source: https://habr.com/ru/post/186718/
All Articles