🍣
PHP __get()と__isset()とNull合体演算子と
PHPの __get() __isset() そしてNull合体演算子ではまりました。
事象
Laravel環境でEloquentのModelの __get() を拡張した際にこのような事象にあいました。
<?php
// hogeは存在しないプロパティ
// __getで動的に値を返している
echo $obj->hoge; // -> 'hoge'
echo $obj->hoge ?? 'fuga'; // -> 'fuga'
$obj->hoge は null ではないのにNull合体演算子で null 判定される?
という感じで悩みました。
Null合体演算子
Null合体演算子 ?? はPHP7から入った新機能です。
isset($hoge) ? $hoge : 'fuga' が $hoge ?? 'fuga' と書けます。
つまり今回の事象は isset($obj->hoge) === false であったということなのです。
__isset()
__isset() は、 isset() あるいは empty() をアクセス不能(protected または private)または存在しないプロパティに対して実行したときに起動します。
存在しないプロパティに対して isset() empty() を実行すると __isset() がコールされるのでそこで適切な値を返さないといけないわけでした。
解決
Illuminate\Database\Eloquent\Model の __isset を追いまして、自分用の存在チェックを滑り込ませました。
ということで__get() を触る時は __isset() もセットでお願いします。(なるべくマジックメソッド使うべからず)
Discussion