Comment gérer L'Offset Non défini dans laravel?
j'obtiens cette erreur quand j'atterris sur la page après la connexion:
ErrorException dans compilé.ligne php 11573: décalage Non défini: 0 (voir: C:xampphtdocscampusgururesourcesviewshome.lame.php)
je sais que la cause de cette erreur est la variable vide que j'ai passé à la vue.
j'ai déjà essayé:
if(isset($blog)) { do something }
<!-Et dans la vue de la lame comme:
{{ $blogs[0]->title or '' }}
Est-il de toute façon je pouvais gérer ce erreur. Ou est-il une meilleure façon de le faire?
5 réponses
Le problème est que $blogs
est en fait défini, et sa valeur est []
(c'est à dire vide array
) donc, cela signifie que isset($blogs)
déclaration évaluera true
. La même chose est valable pour les collections. Si la collection est vide (c'est à dire n'a pas d'éléments mais il est défini) isset($blogs)
va encore évaluer true
mais l'accès $blogs[0]
causera un Undefined offset: 0
erreur.
Vous pouvez essayer les solutions suivantes:
en utilisant count
if(count($blogs)) { /* do something */ }
si $blogs = []
ou $blogs = null
la fonction count
sera de retour à zéro, ce qui signifie qu' $blogs
est vide.
en utilisant empty
if(!empty($blogs)) { /* do something */ }
C'est l'équivalent de l'écriture !isset($var) || $var == false
comme décrit dans la Manuel PHP - vide:
Retourne FALSE si var n'existe et est non vide, non-zéro valeur. Sinon renvoie TRUE.
Les éléments suivants sont considérés comme vides:
""
(un chaîne vide)0
(0 comme un entier)0.0
(0 en tant que flotteur)"0"
(0, comme une chaîne de caractères)NULL
FALSE
array()
(un tableau vide)$var;
(a variable déclarée, mais sans valeur)
Vérifier si la collection est vide
Si $blogs
est un Collection
est suffisant pour vérifier si elle n'est pas vide à l'aide de ' isNotEmpty () méthode:
@if($blogs->isNotEmpty()) <!-- Do your stuff --> @endif
EDIT
j'ai oublié d'ajouter la lame de la syntaxe:
@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 d'aborder certains des questions dans les commentaires. Je pense que votre problème est le suivant:
$blogs
est une collection vide, donc elle est définie mais elle n'a pas d'éléments. Pour cette raison, le if(isset($blogs))
déclaration évaluera true
passage de la première if
condition. Dans votre modèle de lame vous faites la vérification {{ $blogs[0]->title or '' }}
absolument pas égal à<?php isset($blogs[0]->title) ? $blogs[0]->title : '' ?>
comme indiqué dans les commentaires, mais c'est une expression qui va retourner true
ou false
, donc, il ne sera jamais imprimer title
paramètre 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 en fait à l'élément 0
$blogs
collection qui va déclencher l'exception Undefined offset: 0
parce que la collection est en fait vide. Ce que je disais c'est qu'en plus de l'
if(count($blogs)) { /* do something */ }
(qui vérifie que $blogs
est réglé et que sa longueur est plus grande que 0
) dans votre modèle, vous ne devez faire
{{ isset($blogs[0]->title) ? $blogs[0]->title : '' }}
ou de façon plus concise
{{ $blogs[0]->title ?: '' }}
en supposant que le flux de contrôle y arrivera seulement si le $blogs
passé le premier if
. Si le problème persiste, le problème est ailleurs dans votre code IMHO.
essayez la procédure suivante:
{{ isset($blogs[0]) ? $blogs[0]->title : '' }}
si vous utilisez un foreach pour obtenir chaque $ blog - > titre utiliser
@foreach ($blogs as $blog)
{{ $blog->title }}
@endforeach
vous pouvez simplement résoudre cela avec le data_get()
helper.
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: "user1@thisisdevelopment.nl",
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"
>>>
alors dans ce cas:
{{ data_get($blogs[0], 'title', '') }}
data_get()
fonctionnera à la fois sur les tableaux et les objets, retournant la clé ou l'attribut défini dans le second param (cela peut être laravel.dot.notation.style
, ou juste un tableau), Le 3ème paramètre sera la valeur de retour par défaut si l'objet / tableau ou la clé / attribut n'existe pas, la valeur par défaut est NULL.
Edit:
je viens de voir la demande d'explication supplémentaire sur les raisons pour lesquelles le code original ne fonctionnait pas.
Index 0 n'existe tout simplement pas sur le tableau/collection qui est passé à 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"
Il n'a pas d'importance si l'OP a utilisé la lame or default
, il n'arrive même pas à la déclaration ternaire à cause de l'index 0 manquant sur $blogs
.
Edit 2 as demande:
Donc la raison pour laquelle vous obtenez l' Undefined offset: x
l'erreur est due à L'ordre dans lequel PHP évalue le code.
Lame or default
est derrière les coulisses rien de plus qu'un ternaire déclaration:
return preg_replace('/^(?=$)(.+?)(?:\s+or\s+)(.+?)$/si', 'isset() ? : ', $value);
ce qui permettra de faire:
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 $blogs[0]
pour être un objet valide. Pour ce faire, il va essayer et obtenir l'objet de l' $blogs
array à index 0. Mais comme cet indice n'existe pas, il déclenchera L'Exception avec un Undefined offset: 0
.
pour faire ce travail avec la Lame or default
, il faut d'abord s'assurer que $blogs[0]
est défini (et de préférence aussi vérifier que c'est un objet, sinon vous obtiendrez la propriété essayer d'obtenir l'erreur non-object, veuillez noter que cela ne devrait pas être de la responsabilité de la vue.), vous pourrez ensuite utiliser le or default
comme vous le feriez pour tout d'autres temps.
@if (isset($blogs[0]) && is_object($blogs[0]))
{{ $blogs[0]->title or '' }}
@else
// some other default placeholder
@endif
en gros, vous obtiendrez la même erreur de décalage en utilisant data_get()
, parce que l'indice 0 n'existe pas encore.
{{ data_get($blogs[0], 'title', '') }} // Undefined offset: 0
Vous pouvez jouer de sale et de le faire ( cela ne ferait passer aucun examen de code n'importe où et je n'aurais pas du taper ceci du tout, ceci est juste pour illustrer)
{{ data_get($blogs, '0.title', '') }} // Will display '' as it will check if key 0 exists
en tout cas, avec data_get()
vous finiront par faire quelque chose comme cela, vous devez vous assurer d' $blogs[0]
est quelque chose que vous peut travailler avec:
@if (isset($blogs[0]))
{{ data_get($blogs[0], 'title', '') }}
@else
// some other default placeholder
@endif
au Fond, le meilleur choix serait la de s'appuyer sur des indices comme ce à votre avis, ce n'est tout simplement pas la responsabilité de votre point de vue.
Lame or default
fonctionne parfaitement sur des variables individuelles, mais lorsque vous traitez avec les attributs de l'objet, vous devez vous assurer que l'objet (parent) existe.
Si vous avez un objet qui est passé à la vue, et disons que vos données sont "posts" qui se déroule à l'intérieur d'un objet comme celui-ci: $obj->posts.
si vous allez ensuite faire une boucle foreach qui itérerait à chaque poste et imprimerait ses paramètres comme dans l'exemple ci-dessous il fonctionne parfaitement bien quand vous avez réellement des postes.
@foreach($obj->posts as $post)
<h1>$post->title</h1>
<p>$post->content</p>
@endforeach
Avant de faire la boucle que vous voulez vérifier si l'attribut a été défini avec des valeurs. Vous pouvez utiliser isset () pour cela, et puisque c'est une forme spéciale, il peut être utilisé comme isset($obj->posts) ou isset($obj->messages[0]). La différence est que ce dernier ne vérifiera que si la clé du tableau a une valeur alors si votre clé d'index est autre chose que 0, elle retournera false. Par exemple, vous devez:
$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 vérifier est la suivante:
@if(isset($obj->posts))
@foreach($obj->posts as $post)
...
@endoforeach
@endif
je le 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 de la lame:
@if (!empty($allFares) || count($allFares)>0)
@foreach(allFares as $key=>$value)
@endforeach
@endif