公司升級php7 後出現了一個問題,類似這樣 isset($post->user->name)
總是為 false
,之前的php 5.6 就很正常,laravel 版本是5.1.35(很久沒升級了)。
先看看isset
isset
用來偵測變數是否設定
首先我們來看官方的例子
大致上是下面這個意思
<?php class Post { protected $attributes = ['content' => 'foobar']; public function __get($key) { if (isset($this->attributes[$key])) { return $this->attributes[$key]; } } } $post = new Post(); echo isset($post->content); // false
上面這個例子將永遠回傳 false
,因為 foo
不是 Post
的屬性,而是 __get
取出來的
魔術方法 __isset
<?PHP class Post { protected $attributes = ['content' => 'foobar']; public function __get($key) { if (isset($this->attributes[$key])) { return $this->attributes[$key]; } } public function __isset($key) { if (isset($this->attributes[$key])) { return true; } return false; } } $post = new Post(); echo isset($post->content); //true
Eloquent 的範例
Model,簡單的實作。
__get,
__set,
__isset
class Model { // 存放属性 protected $attributes = []; // 存放关系 protected $relations = []; public function __get($key) { if( isset($this->attributes[$key]) ) { return $this->attributes[$key]; } // 找到关联的对象,放在关系里面 if (method_exists($this, $key)) { $relation = $this->$method(); return $this->relations[$method] = $relation; } } public function __set($k, $v) { $this->attributes[$k] = $v; } public function __isset($key) { if (isset($this->attributes[$key]) || isset($this->relations[$key])) { return true; } return false; } }
Post Moel 和一個
User Moel
class Post extends Model { protected function user() { $user = new User(); $user->name = 'user name'; return $user; } } class User extends Model { }
isset
$post = new Post(); echo 'isset 发帖用户:'; echo isset($post->user) ? 'true' : 'false'; // false echo PHP_EOL; echo 'isset 发帖用户的名字:'; echo isset($post->user->name) ? 'true' : 'false'; // false echo PHP_EOL; echo '发帖用户的名字:'; echo $post->user->name; // user name echo PHP_EOL; echo '再次判断 isset 发帖用户的名字:'; echo isset($post->user->name) ? 'true' : 'false'; // true echo PHP_EOL;
答案
分析上面的結果,感覺像是php 7 isset 方法對物件的判斷有了變化,如果先執行一次,
$post->user->name,也就是將user 放在
post#在 ## 的relations
中,這樣isset($post->user)
為true
,接著 isset($post->user- >name)
才為true
。 最後在
的 以上是解決升級php7後isset方法始終為 false的問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!git log
找到了答案,PHP 7 has fixed a bug with __isset which affects both the
native isset and empty methods. This causes specific issues
with checking isset or empty on relations in Eloquent. In
PHP 7 checking if a property exists on an unloaded relation,
for example isset($this->relation->id) is always
returning false because unlike PHP 5.6, PHP 7 is now
checking the offset of each attribute before chaining to
the next one. In PHP 5.6 it would eager load the relation
without checking the offset. This change brings back the
intended behavior of the core Eloquent model __isset method
for PHP 7 so it works like it did in PHP 5.6.
For reference, please check the following link,
specifically Nikita Popov's comment (core PHP dev) -
https://bugs.php.net/bug.php?id=69659