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