首頁 > 後端開發 > PHP7 > 解決升級php7後isset方法始終為 false的問題

解決升級php7後isset方法始終為 false的問題

藏色散人
發布: 2023-02-17 11:46:01
轉載
3145 人瀏覽過

公司升級php7 後出現了一個問題,類似這樣 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 放在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&#39;s comment (core PHP dev) - 
https://bugs.php.net/bug.php?id=69659
登入後複製
大致上是 php7 isset 判斷的時候,會依次判斷。 php5.6 則會預先載入關係。其實 laravel 也早就做了相關的處理,所以升級 laravel 後,自然就沒有這個問題了。

以上是解決升級php7後isset方法始終為 false的問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:learnku.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板