オブジェクト内のプロパティー存在チェックに引っかからない場合

CakePHP5/PHP8.1でコンポーネントがロードされているかどうか調べるために

if(isset($this->Auth)){
}

というようなコードを書いたが、なぜかfalseになる。
その他のmethod_exists()などの類似の関数で試してみても全部False.でも実際にアクセスできるし、デバッガで見てももちろん存在する。
なんでかな?と思ったのですが、コンポーネントのロードにPHPの”マジックメソッド”という機能を使っているのが原因でした。

マジックメソッドの詳細はリンク先をみてもらうとして、簡単に説明するとclassのデフォルトの動きを上書きできちゃうというとんでもない機能。
今回の場合は、実体がない名前のプロパティーがよばれたら、その呼ばれた名前でclassをロードするみたいなことをやっていたようで、そのせいでオブジェクトの中に実態がなかったようです。
classに定義してあるやつはisset()などで存在チェックできますが、このようにマジックメソッドで動的にロードしている場合はissetに引っかからないので注意が必要です。

例に挙げたCakePHPのコンポーネントを調べる場合に限っては  $this->components()->has(‘Auth’) とすれば良いですが、汎用的な方法はどうしたらいいのか?

ケースバイケースだと思いますが、まずなんのマジックメソッドで処理しているのかを突き止める必要があります。継承元のクラスを辿っていけば見つかるはずです。
とりあえず、それっぽいマジックメソッドにブレークを貼って、実際にそのメソッドをコールしてみれば突き止められるはず。
CakePHP5の場合はController::__get()メソッドで処理しているようでした。

ということで、

if($this->__get('Auth')){
// あり
}else{
//なし
}

といった感じにすれば存在チェックが可能です。
あまり使わない機能なので、解決するまでに少々時間を要しました。
動的ロードしているような場合は安易にisset()などでチェックせずに、フレームワークの機能に何か存在チェックするメソッドがないかをしらべて、なさそうだったらマジックメソッドを調べてみるのがいいと思います。

タイトルとURLをコピーしました