如何处理laravel中的Undefined Offset?

vs_*_*ala 17 php undefined offset laravel

登录后登陆页面时收到此错误:

compile.php第11573行中的ErrorException:未定义的偏移量:0(查看:C:\ xampp\htdocs\campusguru\resources\views\home.blade.php)

我知道这个错误的原因是我传递给视图的空变量.

我已经尝试过了:

if(isset($blog)) { do something }
Run Code Online (Sandbox Code Playgroud)

并在刀片视图中:

{{ $blogs[0]->title or '' }}
Run Code Online (Sandbox Code Playgroud)

无论如何我可以处理这个错误.或者有更好的方法吗?

Des*_*901 9

问题是$blogs实际定义的并且它的值是[](即为空array)所以这意味着isset($blogs)语句将评估为true.同样的东西对集合也有效.如果集合为空(即没有元素但已定义)isset($blogs)仍将评估,true但访问$blogs[0]将导致Undefined offset: 0错误.

您可以尝试以下解决方案:

运用 count

if(count($blogs)) { /* do something */ }
Run Code Online (Sandbox Code Playgroud)

if $blogs = []$blogs = null函数count将返回零,以便表示$blogs为空.

运用 empty

if(!empty($blogs)) { /* do something */ }
Run Code Online (Sandbox Code Playgroud)

这相当于PHP手册中!isset($var) || $var == false描述的写作- 空:

如果var存在且具有非空的非零值,则返回FALSE.否则返回TRUE.

以下内容被认为是空的:

  • "" (一个空字符串)
  • 0 (0作为整数)
  • 0.0 (0作为浮点数)
  • "0" (0作为字符串)
  • NULL
  • FALSE
  • array() (一个空数组)
  • $var; (声明的变量,但没有值)
  • 检查集合是否为空

    如果$blogsCollection足以使用`isNotEmpty()方法检查它是否为空:

    @if($blogs->isNotEmpty()) <!-- Do your stuff --> @endif
    
    Run Code Online (Sandbox Code Playgroud)

    编辑

    我忘了添加刀片语法:

    @if(count($blogs)) <!-- Do whatever you like --> @endif
    
    Run Code Online (Sandbox Code Playgroud)

    要么

    @if(!empty($blogs)) <!-- Do whatever you like --> @endif
    
    Run Code Online (Sandbox Code Playgroud)

    编辑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,因为集合实际上是空的.我所说的是除了$blogsUndefined offset: 0

    if(count($blogs)) { /* do something */ }
    
    Run Code Online (Sandbox Code Playgroud)

    (您应该在模板中检查$blogs已设置并且长度大于0)

    {{ isset($blogs[0]->title) ? $blogs[0]->title : '' }}
    
    Run Code Online (Sandbox Code Playgroud)

    或者更简洁

    {{ $blogs[0]->title ?: '' }}
    
    Run Code Online (Sandbox Code Playgroud)

    假设只有$blogs通过第一个控制流才会到达那里if.如果问题仍然存在,则问题出现在您的代码恕我直言的其他地方.


    小智 8

    尝试以下方法:

    {{ isset($blogs[0]) ? $blogs[0]->title : '' }}
    
    Run Code Online (Sandbox Code Playgroud)

    如果您使用foreach获取每个$ blog-> title使用

    @foreach ($blogs as $blog)
      {{ $blog->title }}
    @endforeach
    
    Run Code Online (Sandbox Code Playgroud)


    Rob*_*ert 5

    您可以使用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: "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"
    >>> 
    
    Run Code Online (Sandbox Code Playgroud)

    所以在这种情况下:

    {{ data_get($blogs[0], 'title', '') }}
    
    Run Code Online (Sandbox Code Playgroud)

    data_get()将适用于数组和对象,返回在第二个参数中定义的键或属性(这可以是laravel.dot.notation.style,或只是一个数组),如果对象/数组或键/属性没有,则第三个参数将是默认返回值存在,默认为空。


    编辑:

    刚刚看到关于为什么原始代码不起作用的额外解释的请求。

    传递给视图的数组/集合上根本不存在索引 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"
    
    Run Code Online (Sandbox Code Playgroud)

    如果 OP 使用了 Blade 并不重要or default,它甚至没有进入三元语句,因为缺少 0 索引$blogs


    根据要求编辑 2:

    所以你得到Undefined offset: x错误的原因是因为 PHP 评估代码的顺序。

    Blade'sor default在幕后无非是一个三元声明:

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

    所以这将使:

    isset($blogs[0]->title) ? $blogs[0]->title : ''
    
    Run Code Online (Sandbox Code Playgroud)

    isset()将检查是否设置了对象上的标题,但要这样做,它需要$blogs[0]是一个有效的对象。为了做到这一点,它会尝试从$blogs索引 0处的数组中获取对象。但由于该索引不存在,它将触发 Exception 异常Undefined offset: 0

    为了使这个与 Blade's 一起工作or default,您首先必须确保$blogs[0]已定义(最好还检查它是否是一个对象,否则您将尝试获取非对象的属性错误,请注意,这不应该是视图的责任),之后您就可以or default像其他任何时候一样使用 。

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

    基本上你会在使用时得到相同的偏移错误data_get(),因为索引 0 仍然不存在。

    {{ data_get($blogs[0], 'title', '') }} // Undefined offset: 0
    
    Run Code Online (Sandbox Code Playgroud)

    你可以玩得很脏然后这样做(这不会在任何地方通过任何代码审查,我根本不应该输入这个,这只是为了说明

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

    无论如何,data_get()你最终还是会做这样的事情,因为你需要确保$blogs[0]你可以使用:

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

    底线,最好的选择是不要在您的视图中依赖这样的索引,这根本不是您的视图的责任。

    Bladeor default可以完美地处理单个变量,但是在处理对象属性时,您只需确保(父)对象存在即可。