PHP7中的isset

作者 : OO资源中心 发布时间: 2020-05-10 文章热度:264 共151个字,阅读需1分钟。 本文内容有更新 字体:

升级 php7 后 isset 不太对了

公司升级 php7 后出现了一个问题

类似这样 isset($post->user->name) 始终为 false

之前的 php 5.6 就很正常

laravel 版本是 5.1.35(很久没升级了)

先看看 isset

isset 用来检测变量是否设置

首先我们来看官方的一个例子

大致上是下面这个意思

 '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

那么怎么解决上面那个问题呢?使用魔术方法

 '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 中 找到了答案,

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 后,自然也就没有这个问题了。

《》《》《》


关注微信公众号『OOINK』

第一时间了解最新资源动态关注OO.INK不迷路~

常见问题FAQ

免费下载或者VIP会员专享资源能否直接商用?
本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
下载资源需要解压密码,解压密码是什么?
如下载的资源需要解压密码,请查看下载页右侧查找解压密码;
如没有解压密码请尝试默认解压密码:www.oo.ink 或者 oo.ink
或者联系我们获取解压密码!
1、本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2、分享目的仅供大家学习和交流,请不要用于商业用途!
3、本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
4、如有链接无法下载、失效或广告,请联系管理员处理!
5、本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!

OO.INK资源网 » PHP7中的isset
+已在风雨中度过
为兴趣而改变,为梦想而努力!
+已坚持更新
时时更新,确保最新~

开通SVIP,畅享全站资源下载~

立即了解