升级 php7 后 isset 不太对了
公司升级 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 的例子
看着 laravel 5.1.35 的代码,我们自己写一个简单的例子
先有一个 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。
最后在 Eloquent model 的 git log 中 找到了答案,
大致上是 php7 isset 判断的时候,会依次判断。php5.6 则会预加载关系。其实 laravel 也早在 5 月份就做了相关的处理,所以升级 laravel 后,自然也就没有这个问题了。
推荐教程:《PHP7教程》《PHP教程》《Laravel教程》
以上就是PHP7中的isset的详细内容,更多请关注Work网其它相关文章!