2023/10/05 01:13 編集
※ 削除
投稿2023/10/04 20:32
編集2023/10/04 20:35PHP の empty() でわけのわからない仕様を見つけました。
下記を実行してみてください。
PHP
1<?php 2class Car 3{ 4 protected array $tags; 5 6 public function __get(string $prop): mixed 7 { 8 if (property_exists($this, $prop)) { 9 return $this->{$prop}; 10 } 11 } 12 13 public function __set(string $prop, mixed $val): void 14 { 15 if (property_exists($this, $prop)) { 16 $this->$prop = $val; 17 } 18 } 19} 20 21class CarMapper 22{ 23 public function test(Car $car): void 24 { 25 echo 'そのままだとtrueになる'.PHP_EOL; 26 var_dump(empty($car->tags)); // bool(true) 27 28 echo '代入するとfalseになる'.PHP_EOL; 29 $tags = $car->tags; 30 var_dump(empty($tags)); // bool(false) 31 } 32} 33 34$car = new Car(); 35$car->tags = ['tag1']; 36$carMapper = new CarMapper(); 37$carMapper->test($car);
なんと、「そのままだとtrueになる」のに、「代入するとfalseになる」のです。わけがわかりません…。
一応マニュアルにはこのような記載がございましたが、別に __isset() なんて宣言していませんのでこの記載は関係ないと思いますし。(つまり __isset() が宣言されていなければ empty() は平常運転するだろうと解釈できますし。)
オブジェクトのアクセス不能なプロパティに対して empty() を使用した場合は、もしオーバーロードメソッド __isset() が宣言されていればそれをコールします。
https://www.php.net/manual/ja/function.empty.php
それにもし「> アクセス不能なプロパティに対して empty() を使用」していることが何か関係しているとしても、そもそも最初の var_dump() は「アクセス不能なプロパティを __get() で取得した結果に empty() を使用」していると捉えるべきだと思うのです。
つまりこうではなくて、
PHP
1empty(アクセス不能なプロパティ)
こう捉えるべきだと思うのです。
PHP
1empty(アクセス不能なプロパティを __get() で取得した結果)
なぜならこの outer() は、inner() の結果を利用しているためです。empty() だって中の結果を利用してよ!と思います。なんで中の結果を作る前にアクセスの不能性を判定するのでしょうか。わけがわかりません…。
PHP
1echo outer(inner()); 2function inner(){return 'inner';} 3function outer($str){return 'outer'.$str;}
改めまして質問は2つです。
➀いったいどういうロジックで「そのままだとtrueになる」のに、「代入するとfalseになる」という事象になるのでしょうか?
➁そしてどのようにして「$car->tags のような値(配列のプロパティ)が空配列であること」を確認すべきなのでしょうか?
お詳しい方、よろしくお願い致します。
※尚、empty() だけでなく isset() も同様の事象でした。
質問の➁について、ひとまず Car に以下のような __isset() を置いて解決できました。
PHP
1 public function __isset(string $prop): bool 2 { 3 return property_exists($this, $prop); 4 }
ならば改めて質問になりますが
➂この __isset() はすべてのクラスで絶対に置いておくべきだと思ったのですが、あって困ることはございますか?
もし「オレは empty() や isset() は絶対に通さないのだ!」というなら不要でしょうけれど、あって困ることがなければ備えて置いておくべきだと思いました。(もちろんこれを置かず、➁への回答としてより良いものあれば引き続き➁も募集したいです。)
回答4件
あなたの回答
tips
プレビュー