Maximum function nesting level of '256' reached, aborting!
タイトルのエラーが発生したので原因を調べた。
何を言ってるかよくわからなかったので、ググった。
発生状況とかを書いておこうと思う。
CakePHP3 を使用 HogeBehavior.php を 読み込んだ。
UsersTable.php
public function initialize () { parent::initialize(); $this->addBehavior('Hoge'); } // 続きのコード
そして、 HogeBehavior.php の中に問題があった。
use Cake\ORM\TableRegistry; public initialize () { parent::initialize(); $this->Users = TableRegistry::get('Users'); }
Users から読み出す HogeBehavior.php の中で
TableRegistry::get('User')
をしていたのだ。
原因がわかったので一件落着。
結論
UserTable
から読み込む Behavior
の中で TableRegistry::get('User');
をしてはいけない。
原因調査
だが、せっかくなので事故原因を調査してみた。
vendor の中を読む。
まず、use \Cake\ORM\TableRegistry
とあるので、
TableRegistry の中を読みに行った。
すると、public static function get($alias, array $options = [])
という
メソッドが見つかった。
このメソッドは、static::locator()->get($alias, $options)
をreturn している。
そして、この return の前で error が出ているらしかったので、更に深く潜った。
ところで、
return static::locator()->get($alias, $options);
という書き方は、遅延静的束縛というらしい。
このクラスを継承しているクラスのオブジェクトからこのメソッドが呼ばれた場合、
継承先のlocator()
を読み込むという書き方らしい。(説明が難しいし微妙に違いそう。)
しかし、今回は直接このクラスを呼んでいるので、
return self::locator()->get($alias, $options);
と等価だ。(と思う)
ということで、 \Cake\ORM\TableRegistry クラスの中の
public static function locator(LocatorInterface $locator = null)
を呼んでいる。
このクラスの返り値は
static::$_locator;
であり、ありがたいことにコメントで
* @var \Cake\ORM\Locator\LocatorInterface
とある。
つまり、
Cake\ORM\Locator\TableLocator
が返ってくる。
すなわち、
return static::locator()->get($alias, $options);
の中の
static::locator() = Cake\ORM\Locator\TableLocator
となる。
そこで、Cake\ORM\Locator\TableLocator
クラスのget()
メソッドを探しに行った。
この、179行目、
$this->_instances[$alias] = $this->_create($options);
で呼んでいる、
protected function _create(array $options)
が今回のエラーの原因だった。
このメソッドの中で
return new $options['className']($options);
という風に
$options['className']($options)
を繰り返し new
して返している。
ここがポイントだった。
つまり、
TableRegistry::get('User');
により、UsersTable クラスのオブジェクトが生成される。 そして、UsersTable クラスの
public function initialize()
が動き、もう一度
$this->addBehavior('Hoge');
が呼ばれる。 そして、TableRegistry が動きまたUsersTable クラスが new される。
この繰り返しが256回おこり、 参考サイト1 に書いてあるエラーが起こったのだった。
これが事故原因。
解決方法は、
Cake\ORM\TableRegistry
の使い方に気をつける。
という話でした。
vendor の中見るのたのしー!
感想
なんか、全体的に感想文みたいになってしまったが、
vendor の中を見るのがこんなに楽しいとは思わなかった。
これからも継続して読んでみようと思う。