Смысл в том, что замыкание, передаваемое аргументом, тащит за собой область видимости. Делает это весьма нетривиальным образом - объекту Closure псевдопеременной $this назначает объект, в котором сформировано замыкание. Это не секрет и не новость. Но тут оказывается есть подвох. По порядку.
Допустим есть контейнер (весьма упрощенно)
class Container
{
protected $stack = [];
public function add($callable)
{
$this->stack[] = $callable;
var_dump($this->stack);
}
}
Если зарядить в него анонимную функцию:
class Example
{
public function __construct($container)
{
$container->add(function (){});
}
}
$ex = new Example(new Container);
все будет тип-топ:
array(1) {
[0]=>
object(Closure)#3 (1) {
["this"]=>
object(Example)#1 (0) {
}
}
}
Однако если этот класс юзает контейнер свойством:
class Example
{
protected $container;
public function __construct($container)
{
$this->container = $container;
$this->container->add(function (){});
}
}
$ex = new Example(new Container);
то наблюдается рекурсивная ссылка:
array(1) {
[0]=>
object(Closure)#3 (1) {
["this"]=>
object(Example)#1 (1) {
["container":protected]=>
object(Container)#2 (1) {
["stack":protected]=>
*RECURSION*
}
}
}
}
Печалька в том, что PHP на это никак не реагирует. Может оно и не критично, но я затестил, поджирает немного и время и память. Но это бы полбеды. Важно другое - это не нормальное поведение, и фиг знает, как может аукнуться.
Бороться можно обявив замыкание статическим, но это не всегда подходит.
Так что имейте ввиду. :)
_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.
Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.
Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.