Как обращаться с Undefined Смещение в laravel?

Я получаю эту ошибку, когда я прихожу на страницу после входа в систему:

ОшибкаException в команде compiled.php 11573: Undefined offset: 0 (Вид: C:\XAMPP\HTDOCS\campusguru\ресурсы\вид\home.blade.php)

Я знаю, что причиной этой ошибки является пустая переменная, которую я передал в представление.

Я уже пробовал:

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

и в виде лезвия:

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

В любом случае я могу справиться с этой ошибкой. Или есть лучший способ сделать это?

Ответы

Ответ 1

попробуйте следующее:

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

Если вы используете foreach, чтобы использовать каждый заголовок $blog- > title

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

Ответ 2

Проблема заключается в том, что $blogs фактически определен, и его значение равно [] (т.е. пустое array), поэтому это означает, что оператор isset($blogs) будет оцениваться как true. То же самое справедливо для коллекций. Если коллекция пуста (т.е. Не имеет элементов, но она определена) isset($blogs) будет по-прежнему оцениваться до true, но доступ к $blogs[0] приведет к ошибке Undefined offset: 0.

Вы можете попробовать следующие решения:

Использование count

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

if $blogs = [] или $blogs = null функция count будет возвращать ноль, поэтому означает, что $blogs пуст.

Использование empty

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

Это эквивалент записи !isset($var) || $var == false, как описано в PHP Manual - empty:

Возвращает FALSE, если var существует и имеет непустую ненулевую стоимость. В противном случае возвращается TRUE.

Следующие вещи считаются пустыми:

"" (an пустая строка) 0 (0 как целое число) 0.0 (0 как float) "0" (0 в виде строки) NULL FALSE array() (пустой массив) $var; (a переменная объявлена, но без значения)

Проверка наличия пустой коллекции

Если $blogs является Collection, достаточно проверить, не является ли он пустым, используя ` isNotEmpty() метод:

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

ИЗМЕНИТЬ

Я забыл добавить синтаксис лезвия:

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

или

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

РЕДАКТИРОВАТЬ 2

Я добавляю больше контента к этому ответу, чтобы рассмотреть некоторые из проблем, представленных в комментариях. Я думаю, что ваша проблема заключается в следующем:

$blogs - пустой набор, поэтому он определен, но не содержит элементов. По этой причине оператор if(isset($blogs)) будет оценивать true, передавая первое условие if. В шаблоне вашего клинка вы делаете чек {{ $blogs[0]->title or '' }}, который абсолютно не равен <?php isset($blogs[0]->title) ? $blogs[0]->title : '' ?>, как указано в комментариях, но это выражение, которое вернет true или FALSE, поэтому он никогда не распечатает параметр title, даже если $blogs[0] существует. Проблема здесь в том, что при проверке условия $blogs[0]->title вы фактически обращаетесь к элементу 0 коллекции $blogs, который инициирует исключение Undefined offset: 0, потому что коллекция фактически пуста. Я сказал, что в дополнение к

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

(который проверяет, что $blogs установлен и длина его больше, чем 0) в вашем шаблоне, вы должны сделать

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

или более лаконично

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

предполагая, что поток управления поступит туда, только если $blogs прошел первый if. Если проблема все еще сохраняется, проблема находится в другом месте вашего кода IMHO.

Ответ 3

Вы можете просто решить это с помощью помощника data_get().

Например:

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

Итак, в этом случае:

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

data_get() будет работать как на массивах, так и на объектах, возвращая ключ или атрибут, определенный во втором параметре (это может быть laravel.dot.notation.style или просто массив), третий параметр будет возвратным значением по умолчанию, если объект /array или ключ/атрибут не существует, значение по умолчанию равно null.


Edit:

Только что увидел запрос на дополнительное объяснение причин, по которым исходный код не работал.

Индекс 0 просто не существует в массиве/коллекции, который передается в представление.

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

Не имеет значения, использовал ли OP лезвие or default, он даже не попадает в тернарный оператор из-за отсутствия индекса 0 на $blogs.


Изменить 2 в соответствии с запросом:

Итак, причина, по которой вы получаете ошибку Undefined offset: x, связана с порядком, в котором PHP оценивает код.

Blade or default за кулисами не более чем тройное утверждение:

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

Итак, это сделает:

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

isset() будет проверять, задан ли заголовок для объекта, но для этого требуется, чтобы $blogs[0] был допустимым объектом. Чтобы сделать это, он попытается получить объект из массива $blogs в индексе 0. Но поскольку этот индекс не существует, он вызывает Исключение с Undefined offset: 0.

Чтобы сделать эту работу с Blade or default, вам сначала нужно убедиться, что $blogs[0] определен (и желательно также проверить, что это объект, иначе вы получите попытку получить свойство не- объектная ошибка, обратите внимание, что это не должно быть зависеть от представления), после чего вы сможете использовать or default, как и в любое другое время.

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

В основном вы получите ту же ошибку смещения при использовании data_get(), потому что индекс 0 все еще не существует.

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

Вы можете играть грязно и делать это (это не будет проходить ни одного обзора кода в любом месте, и я не должен был набирать это вообще, это просто для иллюстрации)

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

Во всяком случае, с data_get() вы все равно будете делать что-то вроде этого, так как вам нужно убедиться, что $blogs[0] - это то, с чем вы можете работать:

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

Внизу, лучший вариант будет не, чтобы полагаться на такие индексы, как это в вашем представлении, это просто не несет ответственности за ваше мнение.

Blade or default отлично работает с одиночными переменными, но при работе с объектными атрибутами вам просто нужно убедиться, что объект (родительский) существует при этом.

Ответ 4

Если у вас есть объект, переданный в представление, и пусть ваши данные являются "сообщениями", которые хранятся внутри такого объекта: $ Obj- > сообщений.

Если вы перейдете и выполните цикл foreach, который будет проходить через каждый пост и распечатывать его параметры, как в приведенном ниже примере, он отлично работает, когда у вас действительно есть сообщения.

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

Перед выполнением цикла вы хотите проверить, установлен ли атрибут со значениями. Вы можете использовать isset() для этого, и поскольку это специальная форма, она может использоваться как isset ($ obj- > posts) или isset ($ obj- > posts [0]). Разница в том, что последний проверяет только, имеет ли ключ массива какое-либо значение, поэтому, если ваш индексный ключ ничего, кроме 0, он вернет false. Например, у вас есть:

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

Как я могу сделать проверку:

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

Ответ 5

Я делаю это в контроллере:

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

ИЛИ в лезвии:

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

                @endforeach
   @endif