PHP7中的isset
php  /  管理员 发布于 7年前   215
升级 php7 后 isset 不太对了
公司升级 php7 后出现了一个问题
类似这样 isset($post->user->name) 始终为 false
之前的 php 5.6 就很正常
laravel 版本是 5.1.35(很久没升级了)
先看看 isset
isset 用来检测变量是否设置
首先我们来看官方的一个例子
大致上是下面这个意思
<?phpclass 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
那么怎么解决上面那个问题呢?使用魔术方法
<?PHPclass 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'; // falseecho PHP_EOL;echo 'isset 发帖用户的名字:';echo isset($post->user->name) ? 'true' : 'false'; // falseecho PHP_EOL;echo '发帖用户的名字:';echo $post->user->name; // user nameecho PHP_EOL;echo '再次判断 isset 发帖用户的名字:';echo isset($post->user->name) ? 'true' : 'false'; // trueecho PHP_EOL;
答案
分析上面的结果,感觉像是 php 7 isset 方法对对象的判断有了变化,如果先执行一次,$post->user->name,也就是将 user 放在 post 的 relations 中,这样 isset ($post->user) 为 true,随后 isset ($post->user->name) 才为 true。
最后在 Eloquent model 的 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
大致上是 php7 isset 判断的时候,会依次判断。php5.6 则会预加载关系。其实 laravel 也早在 5 月份就做了相关的处理,所以升级 laravel 后,自然也就没有这个问题了。
推荐教程:《PHP7教程》《PHP教程》《Laravel教程》
以上就是PHP7中的isset的详细内容,更多请关注其它相关文章!
122 在
学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
Copyright·© 2019 侯体宗版权所有·
粤ICP备20027696号