wake-up-neo.net

Umgang mit undefined Offset in Laravel

Ich erhalte diese Fehlermeldung, wenn ich nach dem Einloggen auf der Seite lande:

ErrorException in compiled.php Zeile 11573: Undefinierter Offset: 0 (Ansicht: C:\xampp\htdocs\campusguru\resources\views\home.blade.php)

Ich weiß, dass die Ursache dieses Fehlers die leere Variable ist, die ich an die Ansicht übergeben habe.

Ich habe schon versucht:

if(isset($blog)) { do something }

und in der Blattsicht als:

{{ $blogs[0]->title or '' }}

Gibt es sowieso ich könnte diesen Fehler behandeln. Oder gibt es einen besseren Weg, dies zu tun?

15
vs_lala

Das Problem ist, dass $blogs tatsächlich definiert ist und der Wert [] (d. H. Leer array) ist. Dies bedeutet, dass die isset($blogs)-Anweisung zu true ausgewertet wird. Gleiches gilt für Sammlungen. Wenn eine Auflistung leer ist (d. H. Keine Elemente enthält, aber definiert ist), wird isset($blogs) weiterhin in true ausgewertet, der Zugriff auf $blogs[0] führt jedoch zu einem Undefined offset: 0-Fehler.

Sie können die folgenden Lösungen ausprobieren:

count verwenden

if(count($blogs)) { /* do something */ }

wenn $blogs = [] oder $blogs = null die Funktion count Null zurückgibt, bedeutet dies, dass $blogs leer ist.

empty verwenden

if(!empty($blogs)) { /* do something */ }

Dies ist das Äquivalent zum Schreiben von !isset($var) || $var == false wie im Handbuch PHP beschrieben - empty :

Kehrt zurück FALSE Wenn var existiert und eine nicht leere, ungleich Null hat Wert. Ansonsten kehrt zurück WAHR.

Die folgenden Dinge gelten als leer: 

  • "" (eine leere Zeichenfolge)
  • 0 (0 als ganze Zahl)
  • 0.0 (0 als float)
  • "0" (0 als Zeichenfolge)
  • NULL
  • FALSE
  • array() (ein leeres Array)
  • $var; (eine Variable wurde deklariert, aber ohne Wert)
  • Prüfen, ob eine Sammlung leer ist

    Wenn $blogs eine Collection ist, reicht es aus, um zu überprüfen, ob sie nicht leer ist, und zwar mit `isNotEmpty () method:

    @if($blogs->isNotEmpty()) <!-- Do your stuff --> @endif
    

    EDIT

    Ich habe vergessen, die Blade-Syntax hinzuzufügen:

    @if(count($blogs)) <!-- Do whatever you like --> @endif
    

    oder

    @if(!empty($blogs)) <!-- Do whatever you like --> @endif
    

    EDIT 2

    Ich füge dieser Antwort mehr Inhalt hinzu, um einige der in den Kommentaren behandelten Probleme zu lösen. Ich denke, dein Problem ist folgendes:

    $blogs ist eine leere Sammlung, also definiert, aber keine Elemente. Aus diesem Grund wird die if(isset($blogs))-Anweisung zu true ausgewertet, wobei die erste if-Bedingung übergeben wird. In Ihrer Blade-Vorlage führen Sie die Überprüfung {{ $blogs[0]->title or '' }} durch, die absolut nicht gleich<?php isset($blogs[0]->title) ? $blogs[0]->title : '' ?> ist, wie in den Kommentaren angegeben. Es handelt sich jedoch um einen Ausdruck, der true oder false zurückgibt, sodass der Parameter title niemals ausgegeben wird, selbst wenn $blogs[0] existiert. Das Problem hierbei ist, dass Sie bei der Überprüfung der Bedingung $blogs[0]->title tatsächlich auf das Element 0 der $blogs-Auflistung zugreifen, das die Ausnahme Undefined offset: 0 auslösen wird, da die Auflistung tatsächlich leer ist. Was ich sagte, ist das zusätzlich zum

    if(count($blogs)) { /* do something */ }
    

    (das überprüft, ob $blogs eingestellt ist und die Länge größer als 0 ist) in Ihrer Vorlage, die Sie ausführen sollten

    {{ isset($blogs[0]->title) ? $blogs[0]->title : '' }}
    

    oder prägnanter

    {{ $blogs[0]->title ?: '' }}
    

    angenommen, der Kontrollfluss wird nur dort ankommen, wenn der $blogs die erste if übergeben hat. Wenn das Problem weiterhin besteht, liegt das Problem IMHO an anderer Stelle in Ihrem Code.

    8
    Desh901

    versuche Folgendes:

    {{ isset($blogs[0]) ? $blogs[0]->title : '' }}
    

    Wenn Sie ein foreach verwenden, um jeden $ blog-> Titel zu erhalten, verwenden Sie

    @foreach ($blogs as $blog)
      {{ $blog->title }}
    @endforeach
    
    6
    iisurge

    Sie können dies einfach mit dem Helper data_get() lösen.

    Zum Beispiel:

    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"
    >>> 
    

    Also in diesem Fall:

    {{ data_get($blogs[0], 'title', '') }}
    

    data_get() funktioniert sowohl auf Arrays als auch auf Objekten und gibt den im zweiten Parameter definierten Schlüssel oder das angegebene Attribut zurück (dies kann laravel.dot.notation.style oder nur ein Array sein). Der dritte Parameter ist der Standardwert für die Rückgabe des Objekts/Arrays oder des Schlüssels/Attributs ist nicht vorhanden, der Standardwert ist null.


    Bearbeiten:

    Ich sah gerade die Bitte um zusätzliche Erklärung, warum der ursprüngliche Code nicht funktionierte.

    Der Index 0 ist für das Array/die Sammlung, das an die Ansicht übergeben wird, einfach nicht vorhanden.

    >>> $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"
    

    Es ist egal, ob OP das Blade or default verwendet hat, es kommt nicht einmal zur ternären Anweisung, da der Index 0 für $blogs fehlt. 


    Bearbeiten Sie 2 wie gewünscht:

    Der Grund, warum Sie den Undefined offset: x-Fehler erhalten, liegt in der Reihenfolge, in der PHP den Code auswertet.

    Blades or default ist hinter den Kulissen nichts weiter als eine ternäre Aussage:

    return preg_replace('/^(?=\$)(.+?)(?:\s+or\s+)(.+?)$/si', 'isset($1) ? $1 : $2', $value);
    

    Das wird also machen:

    isset($blogs[0]->title) ? $blogs[0]->title : ''
    

    isset() prüft, ob der Titel für das Objekt festgelegt ist, aber dazu muss $blogs[0] ein gültiges Objekt sein. Dazu versucht es, das Objekt aus dem $blogs-Array am Index 0 abzurufen. Da dieser Index jedoch nicht vorhanden ist, löst er die Exception mit einem Undefined offset: 0 aus. 

    Damit dies mit Blades or default funktioniert, müssen Sie zunächst sicherstellen, dass $blogs[0] definiert ist (und vorzugsweise auch prüfen, ob es ein Objekt ist. Andernfalls erhalten Sie den Versuch, die Eigenschaft eines Nicht-Objektfehlers bitte.) Zu erhalten Beachten Sie, dass dies nicht in der Verantwortung der Ansicht liegen sollte). Danach können Sie den or default wie gewohnt verwenden.

    @if (isset($blogs[0]) && is_object($blogs[0]))
        {{ $blogs[0]->title or '' }}
    @else
        // some other default placeholder
    @endif
    

    Grundsätzlich erhalten Sie bei Verwendung von data_get() den gleichen Offset-Fehler, da Index 0 noch nicht vorhanden ist.

    {{ data_get($blogs[0], 'title', '') }} // Undefined offset: 0
    

    Sie könnten schmutzig spielen und dies tun (dies würde keine Codeüberprüfung nirgendwo passieren und ich hätte dies überhaupt nicht eingeben sollen, dies ist nur zur Veranschaulichung)

    {{ data_get($blogs, '0.title', '') }} // Will display '' as it will check if key 0 exists
    

    Mit data_get() würden Sie sowieso trotzdem etwas tun, da Sie sichergehen müssten, dass $blogs[0] etwas ist, mit dem Sie arbeiten können:

    @if (isset($blogs[0]))
        {{ data_get($blogs[0], 'title', '') }}
    @else
        // some other default placeholder
    @endif
    

    Unterm Strich wäre die beste Option nicht, um sich in Ihrer Ansicht auf solche Indizes zu verlassen. Dies liegt einfach nicht in der Verantwortung Ihrer Ansicht.

    or default von Blade funktioniert perfekt mit einzelnen Variablen. Beim Umgang mit Objektattributen müssen Sie lediglich sicherstellen, dass das (übergeordnete) Objekt vorhanden ist.

    3
    Robert

    Wenn Sie ein Objekt haben, das an die Ansicht übergeben wird, und sagen Sie, Ihre Daten sind "Posts", die in einem Objekt wie dem folgenden gehalten werden: $ Obj-> posts.

    Wenn Sie dann eine foreach-Schleife ausführen, durch die jeder Beitrag durchlaufen würde, und seine Parameter wie im folgenden Beispiel ausgedruckt werden, funktioniert er perfekt, wenn Sie tatsächlich Beiträge haben.

    @foreach($obj->posts as $post)
       <h1>$post->title</h1>
       <p>$post->content</p>
    @endforeach
    

    Bevor Sie die Schleife ausführen, sollten Sie überprüfen, ob das Attribut mit Werten festgelegt wurde. Sie können dazu isset () verwenden, und da es sich um eine spezielle Form handelt, kann es als isset ($ obj-> posts) oder isset ($ obj-> posts [0]) verwendet werden. Der Unterschied besteht darin, dass der letztere nur überprüft, ob der Array-Schlüssel einen Wert hat. Wenn Ihr Indexschlüssel nicht 0 ist, wird der Wert false zurückgegeben. Zum Beispiel haben Sie:

    $foo = ['first' => somevalue1, 'second' => somevalue2];
    isset($foo[0]); //returns false
    isset($foo['first']); //returns true
    isset($foo); //returns true
    

    Die Art, wie ich den Check machen würde, ist folgende:

    @if(isset($obj->posts))
       @foreach($obj->posts as $post)
          ...
       @endoforeach
    @endif
    
    1
    Nino Korent

    Ich mache diesen Weg im Controller: 

     if (empty($allFares) || count($allFares)==0){
                return back()->withError('No Fare Found For The City!');
            }
    

    ODER in der Klinge: 

       @if (!empty($allFares) || count($allFares)>0)
                   @foreach(allFares as $key=>$value)
    
                    @endforeach
       @endif
    
    0
    John