最新公告
  • 欢迎您光临码农资源网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!加入我们
  • 解决升级php7后isset方法始终为 false的问题

    公司升级 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 放在 postrelations 中,这样 isset($post->user) true,随后 isset($post->user->name) 才为 true

    最后在 Eloquent modelgit 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 也早就做了相关的处理,所以升级 laravel 后,自然也就没有这个问题了。


    以上就是【解决升级php7后isset方法始终为 false的问题】的详细内容。

    想要了解更多内容,请持续关注码农资源网,一起探索发现编程世界的无限可能!

    本站部分资源来源于网络,仅限用于学习和研究目的,请勿用于其他用途。

    如有侵权请发送邮件至1943759704@qq.com删除

    想要了解更多内容,请持续关注码农资源网,一起探索发现编程世界的无限可能!
    本站部分资源来源于网络,仅限用于学习和研究目的,请勿用于其他用途。
    如有侵权请发送邮件至1943759704@qq.com删除

    码农资源网 » 解决升级php7后isset方法始终为 false的问题
    • 7会员总数(位)
    • 25846资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 293稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情