Je reçois cette erreur lorsque j'atterris sur la page après m'être connecté:
ErreurException dans la ligne compiled.php 11573: offset non défini: 0 (vue: C:\xampp\htdocs\campusguru\resources\views\home.blade.php)
Je sais que la cause de cette erreur est la variable vide que j'ai transmise à la vue.
J'ai déjà essayé:
if(isset($blog)) { do something }
et en vue de lame comme:
{{ $blogs[0]->title or '' }}
Y at-il de toute façon je pourrais gérer cette erreur. Ou y a-t-il une meilleure façon de le faire?
Le problème est que $blogs
est en réalité défini et que sa valeur est []
(c'est-à-dire vide array
), ce qui signifie que l'instruction isset($blogs)
sera évaluée à true
. La même chose est valable pour les collections. Si une collection est vide (c'est-à-dire qu'elle ne contient aucun élément mais qu'elle est définie), isset($blogs)
sera toujours évalué à true
mais l'accès à $blogs[0]
provoquera une erreur Undefined offset: 0
.
Vous pouvez essayer les solutions suivantes:
_ {En utilisant count
if(count($blogs)) { /* do something */ }
si $blogs = []
ou $blogs = null
, la fonction count
retournera zéro, ce qui signifie que $blogs
est vide.
_ {En utilisant empty
if(!empty($blogs)) { /* do something */ }
Ceci équivaut à écrire !isset($var) || $var == false
comme décrit dans le manuel PHP - vide :
Résultats FALSE si var existe et a un non vide, non nul valeur. Sinon retourne VRAI.
Les éléments suivants sont considérés comme vides:
""
(une chaîne vide )0
(0 sous forme d'entier)0.0
(0 en tant que float)"0"
(0 sous forme de chaîne)NULL
FALSE
array()
(un tableau vide)$var;
(une variable .__ déclarée, mais sans valeur)
Vérifier si une collection est vide
Si $blogs
est une Collection
suffit pour vérifier si elle n'est pas vide à l'aide de `isNotEmpty () method:
@if($blogs->isNotEmpty()) <!-- Do your stuff --> @endif
MODIFIER
J'ai oublié d'ajouter la syntaxe de la lame:
@if(count($blogs)) <!-- Do whatever you like --> @endif
ou
@if(!empty($blogs)) <!-- Do whatever you like --> @endif
EDIT 2
J'ajoute plus de contenu à cette réponse afin de résoudre certains des problèmes présentés dans les commentaires. Je pense que votre problème est le suivant:
$blogs
est une collection vide, elle est donc définie mais elle ne contient aucun élément. Pour cette raison, l'instruction if(isset($blogs))
sera évaluée à true
en passant la première condition if
. Dans votre modèle de lame, vous effectuez le contrôle {{ $blogs[0]->title or '' }}
qui est absolument différent de<?php isset($blogs[0]->title) ? $blogs[0]->title : '' ?>
comme indiqué dans les commentaires, mais il s'agit d'une expression qui renverra true
ou false
, de sorte qu'il ne sera jamais imprimé le paramètre title
. même si $blogs[0]
existe. Le problème ici est que lors de la vérification de la condition $blogs[0]->title
, vous accédez réellement à l'élément 0
de la collection $blogs
qui déclenchera l'exception Undefined offset: 0
car la collection est en fait vide. Ce que je disais, c'est qu'en plus de la
if(count($blogs)) { /* do something */ }
(qui vérifie que $blogs
est défini et que sa longueur est supérieure à 0
) dans votre modèle, vous devez le faire
{{ isset($blogs[0]->title) ? $blogs[0]->title : '' }}
ou plus concise
{{ $blogs[0]->title ?: '' }}
en supposant que le flux de contrôle n'y arrivera que si le $blogs
a passé la première if
. Si le problème persiste, le problème est ailleurs dans votre code IMHO.
essayez ce qui suit:
{{ isset($blogs[0]) ? $blogs[0]->title : '' }}
Si vous utilisez un foreach pour obtenir chaque utilisation de $ blog-> title
@foreach ($blogs as $blog)
{{ $blog->title }}
@endforeach
Vous pouvez simplement résoudre ce problème avec l'assistant data_get()
.
Par exemple:
php artisan tink
Psy Shell v0.8.11 (PHP 7.0.22-0ubuntu0.16.04.1 — cli) by Justin Hileman
>>>
>>> $a = collect([[], null, App\Models\User::find(1)]);
=> Illuminate\Support\Collection {#887
all: [
[],
null,
App\Models\User {#896
id: 1,
name: "user1",
email: "[email protected]",
last_name: "Gabrielle",
first_name: "Rempel",
deleted_at: null,
created_at: "2017-08-12 15:32:01",
updated_at: "2017-09-05 12:23:54",
},
],
}
>>> data_get($a[0], 'name', 'nope');
=> "nope"
>>> data_get($a[1], 'name', 'nope');
=> "nope"
>>> data_get($a[2], 'name', 'nope');
=> "user1"
>>>
Donc dans ce cas:
{{ data_get($blogs[0], 'title', '') }}
data_get()
fonctionnera à la fois sur les tableaux et les objets, en renvoyant la clé ou l'attribut défini dans le deuxième paramètre (il peut s'agir de laravel.dot.notation.style
ou simplement un tableau), le troisième paramètre sera la valeur de retour par défaut si l'objet/le tableau ou la clé/l'attribut n'existe pas, la valeur par défaut est null.
Modifier:
Je viens de voir la demande d'explication supplémentaire sur la raison pour laquelle le code d'origine ne fonctionnait pas.
L'index 0 n'existe tout simplement pas sur le tableau/la collection transmis à la vue.
>>> $a = [1 => App\Models\User::find(1)];
=> [
1 => App\Models\User {#890
id: 1,
name: "user1",
// ... etc
},
]
>>> $a[0]->name ?: 'nope';
PHP error: Undefined offset: 0 on line 1
>>> $a[1]->name ?: 'nope';
=> "user1"
Peu importe si OP utilisait la lame or default
, elle ne parvient même pas à la déclaration ternaire à cause de l'index 0 manquant sur $blogs
.
Éditez 2 comme demandé:
Donc, la raison pour laquelle vous obtenez l'erreur Undefined offset: x
est due à l'ordre dans lequel PHP évalue le code.
Le or default
de Blade est dans les coulisses rien de plus qu'une déclaration ternaire:
return preg_replace('/^(?=\$)(.+?)(?:\s+or\s+)(.+?)$/si', 'isset($1) ? $1 : $2', $value);
Cela fera donc:
isset($blogs[0]->title) ? $blogs[0]->title : ''
isset()
vérifiera si le titre de l'objet est défini, mais pour ce faire, il faudra que $blogs[0]
soit un objet valide. Pour ce faire, il essaiera d'obtenir l'objet du tableau $blogs
à l'index 0. Mais comme cet index n'existe pas, il déclenchera l'exception avec un Undefined offset: 0
.
Pour que cela fonctionne avec le or default
de Blade, vous devez d'abord vous assurer que $blogs[0]
est défini (et de préférence aussi vérifier qu'il s'agit d'un objet, sinon vous obtiendrez la tentative d'obtenir la propriété d'erreur non-objet, veuillez noter que cela ne devrait pas être la responsabilité de la vue ), après quoi vous pourrez utiliser le or default
comme vous le feriez à tout autre moment.
@if (isset($blogs[0]) && is_object($blogs[0]))
{{ $blogs[0]->title or '' }}
@else
// some other default placeholder
@endif
En règle générale, vous obtiendrez la même erreur de décalage lors de l'utilisation de data_get()
, car l'index 0 n'existe toujours pas.
{{ data_get($blogs[0], 'title', '') }} // Undefined offset: 0
Vous pouvez jouer en sale et faire ceci ( cela ne passerait à aucune révision de code et je n’aurais pas dû taper cela du tout, c’est juste pour illustrer )
{{ data_get($blogs, '0.title', '') }} // Will display '' as it will check if key 0 exists
Quoi qu'il en soit, avec data_get()
, vous finirez toujours par faire quelque chose comme ceci, car vous devez vous assurer que $blogs[0]
est quelque chose avec lequel vous pouvez travailler:
@if (isset($blogs[0]))
{{ data_get($blogs[0], 'title', '') }}
@else
// some other default placeholder
@endif
En bout de ligne, la meilleure option serait pas de vous fier à des index comme celui-ci, selon vous, ce n’est tout simplement pas de votre responsabilité.
Le or default
de Blade fonctionne parfaitement sur des variables uniques, mais lorsque vous utilisez des attributs d'objet, vous devez simplement vous assurer que l'objet (parent) existe bien.
Si vous avez un objet qui est passé à la vue et supposons que vos données sont des "posts" qui sont conservés dans un objet comme celui-ci: $ Obj-> posts.
Si vous effectuez ensuite une boucle foreach qui parcourt chaque publication et en affiche les paramètres, comme dans l'exemple ci-dessous, cela fonctionne parfaitement lorsque vous avez des publications.
@foreach($obj->posts as $post)
<h1>$post->title</h1>
<p>$post->content</p>
@endforeach
Avant de faire la boucle, vous voudrez vérifier si l'attribut a été défini avec des valeurs. Vous pouvez utiliser isset () pour cela, et puisqu'il s'agit d'un formulaire spécial, il peut être utilisé comme isset ($ obj-> posts) ou isset ($ obj-> posts [0]). La différence est que ce dernier ne vérifiera que si la clé du tableau a une valeur, donc si votre clé d'index est différente de 0, elle retournera false. Par exemple, vous avez:
$foo = ['first' => somevalue1, 'second' => somevalue2];
isset($foo[0]); //returns false
isset($foo['first']); //returns true
isset($foo); //returns true
La façon dont je ferais le chèque est la suivante:
@if(isset($obj->posts))
@foreach($obj->posts as $post)
...
@endoforeach
@endif
Je fais de cette façon dans le contrôleur:
if (empty($allFares) || count($allFares)==0){
return back()->withError('No Fare Found For The City!');
}
OU en lame:
@if (!empty($allFares) || count($allFares)>0)
@foreach(allFares as $key=>$value)
@endforeach
@endif