>백엔드 개발 >PHP7 >php7로 업그레이드 후 isset 메소드가 항상 false인 문제 해결

php7로 업그레이드 후 isset 메소드가 항상 false인 문제 해결

藏色散人
藏色散人앞으로
2019-03-29 17:15:343126검색

회사에서 php7을 업그레이드한 후 문제가 발생했습니다. isset($post->user->name) 과 같은 내용은 항상 false였으며 이전 PHP 5.6은 Normal., laravel 버전은 5.1.35입니다(오랫동안 업그레이드되지 않았습니다).  isset($post->user->name) 始终为 false,之前的php 5.6 就很正常,laravel 版本是 5.1.35(很久没升级了)。

先看看isset

isset 用来检测变量是否设置

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

大致上是下面这个意思

<?php

class Post
{
    protected $attributes = [&#39;content&#39; => &#39;foobar&#39;];

    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 = [&#39;content&#39; => &#39;foobar&#39;];

    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 = &#39;user name&#39;;
        return $user;
    }

}

class User extends Model
{
}

好了来验证一下isset

$post = new Post();

echo &#39;isset 发帖用户:&#39;;
echo isset($post->user) ? &#39;true&#39; : &#39;false&#39;;  // false
echo PHP_EOL;

echo &#39;isset 发帖用户的名字:&#39;;
echo isset($post->user->name) ? &#39;true&#39; : &#39;false&#39;;  // false
echo PHP_EOL;

echo &#39;发帖用户的名字:&#39;;
echo $post->user->name;    // user name
echo PHP_EOL;

echo &#39;再次判断 isset 发帖用户的名字:&#39;;
echo isset($post->user->name) ? &#39;true&#39; : &#39;false&#39;;   // true
echo PHP_EOL;

答案

分析上面的结果,感觉像是 php 7 isset 方法对对象的判断有了变化,如果先执行一次,$post->user->name,也就是将 user 放在 postrelations 中,这样 isset($post->user) true,随后 isset($post->user->name) 才为 true

最后在 Eloquent modelgit log

isset를 먼저 살펴보세요

isset는 변수가 설정되었는지 감지하는 데 사용됩니다🎜🎜먼저 공식 예제를 살펴보겠습니다🎜 🎜대략 다음을 의미합니다🎜
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&#39;s comment (core PHP dev) - 
https://bugs.php.net/bug.php?id=69659
🎜위의 예는 항상 false를 반환합니다. 왜냐하면 foo Post 의 속성이 아니지만 이기 때문입니다. > __get Taken out🎜🎜Magic method __isset🎜🎜 그렇다면 위의 문제를 어떻게 해결해야 할까요? 마법의 방법을 사용하세요🎜rrreee🎜Eloquent와 유사한 예🎜🎜laravel 5.1.35의 코드를 보면 우리가 직접 간단한 예를 작성해봅니다🎜🎜먼저 Model가 있습니다 >, 간단한 실현. __get, __set, __isset🎜rrreee🎜 그런 다음 Post Moel User Moel🎜rrreee🎜좋아, <code>isset를 검증하자🎜rrreee🎜답변🎜🎜위 결과를 분석해 보면 php 7 isset 같은 느낌이다. 한번 실행하면 $post->user->name, 즉 user가 post에 위치하게 됩니다. code> 관계, isset($post->user) true이고 isset($post->user- >name ) true입니다. 🎜🎜결국 Eloquent modelgit log에서 답을 찾았습니다. 🎜rrreee🎜대략 php7 isset이 심사할 때 순차적으로 심사하게 됩니다. php5.6은 관계를 미리 로드합니다. 사실 laravel에서는 이미 관련 처리를 해두었기 때문에 laravel을 업그레이드하고 나면 이 문제는 자연스럽게 사라질 것입니다. 🎜

위 내용은 php7로 업그레이드 후 isset 메소드가 항상 false인 문제 해결의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 learnku.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제