Un problème est survenu après la mise à niveau de php7 par l'entreprise, quelque chose comme ça isset($post->user->name)
était toujours false
Le php 5.6 précédent était normal et la version de Laravel était 5.1.35 (elle n'a pas été mise à niveau depuis longtemps). .
Jetons un coup d'œil d'abordisset
isset
est utilisé pour détecter si la variable est définie
Jetons d'abord un coup d'œil à un exemple officiel
signifie à peu près ce qui suit
<?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
L'exemple ci-dessus renverra toujours false
, car foo
n'est pas un attribut de Post
, mais est retiré de __get
Méthode magique __isset
Alors comment résoudre le problème ci-dessus ? Utiliser la méthode magique
<?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
Un exemple similaire à Eloquent
En regardant le code de laravel 5.1.35, nous écrivons nous-mêmes un exemple simple
Il y a d'abord aModel
, mise en œuvre simple. __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; } }
Ensuite, nous définissons un Post Moel
et un User Moel
class Post extends Model { protected function user() { $user = new User(); $user->name = 'user name'; return $user; } } class User extends Model { }
D'accord, vérifions-le 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;
Réponse
En analysant les résultats ci-dessus, il semble que le jugement de l'objet par la méthode php 7 isset
a changé s'il est exécuté une fois, $post->user->name
, c'est-à-dire mettre l'utilisateur dans post
de relations
, de sorte que isset($post->user)
devienne true
, puis isset($post->user->name)
devienne true
.
Enfin trouvé la réponse dans Eloquent model
de 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
c'est à peu près quand php7 juge, il jugera dans l'ordre. php5.6 préchargera les relations. En fait, Laravel a déjà effectué le traitement associé, donc après la mise à niveau de Laravel, ce problème disparaîtra naturellement.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!