Php 如何处理laravel中未定义的偏移?
我在登录后登录页面时遇到此错误: compiled.php行11573中的ErrorException:未定义的偏移量:0(视图: C:\xampp\htdocs\campusguru\resources\views\home.blade.php) 我知道这个错误的原因是我传递给视图的空变量Php 如何处理laravel中未定义的偏移?,php,laravel,undefined,offset,Php,Laravel,Undefined,Offset,我在登录后登录页面时遇到此错误: compiled.php行11573中的ErrorException:未定义的偏移量:0(视图: C:\xampp\htdocs\campusguru\resources\views\home.blade.php) 我知道这个错误的原因是我传递给视图的空变量 >>> $a = [1 => App\Models\User::find(1)]; => [ 1 => App\Models\User {#890
>>> $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"
我已经试过:
if(isset($blog)) { do something }
在刀片视图中显示为:
{{ $blogs[0]->title or '' }}
不管怎样,我都可以处理这个错误。或者有更好的方法吗?尝试以下方法:
{{ isset($blogs[0]) ? $blogs[0]->title : '' }}
@if(isset($obj->posts))
@foreach($obj->posts as $post)
...
@endoforeach
@endif
如果您使用foreach获取每个$blog->title,请使用
@foreach ($blogs as $blog)
{{ $blog->title }}
@endforeach
如果您有一个传递到视图的对象,假设您的数据是“posts”,它保存在一个对象中,如下所示: $obj->posts 如果你接着去做一个foreach循环,它会在每一篇文章中迭代并打印出它的参数,就像下面的例子一样,当你真的有文章时,它工作得非常好
@foreach($obj->posts as $post)
<h1>$post->title</h1>
<p>$post->content</p>
@endforeach
我进行检查的方式如下:
{{ isset($blogs[0]) ? $blogs[0]->title : '' }}
@if(isset($obj->posts))
@foreach($obj->posts as $post)
...
@endoforeach
@endif
问题是,
$blogs
实际上是定义的,它的值是[]
(即空的数组
),因此这意味着isset($blogs)
语句将计算为true
。同样的道理也适用于集合。如果集合为空(即没有元素但已定义)isset($blogs)
仍将计算为true
,但访问$blogs[0]
将导致未定义的偏移量:0
错误
您可以尝试以下解决方案:
使用计数
if(count($blogs)) { /* do something */ }
if(!empty($blogs)) { /* do something */ }
如果$blogs=[]
或$blogs=null
函数count
将返回零,这意味着$blogs
为空
使用空
if(count($blogs)) { /* do something */ }
if(!empty($blogs)) { /* do something */ }
这相当于编写!isset($var)| |$var==false
如中所述:
如果var存在且具有非空、非零的值,则返回FALSE
价值否则返回TRUE
以下内容被认为是空的:”
(一个
空字符串)0
(0作为整数)0.0
(0作为整数)
浮动)“0”
(0作为字符串)NULL
FALSE
array()
(空数组)(a)
已声明变量,但没有值)
检查集合是否为空
如果$blogs
是集合
足以使用以下方法检查其是否为空:
(检查模板中是否设置了$blogs
,并且其长度是否大于0
)
{{ isset($blogs[0]->title) ? $blogs[0]->title : '' }}
或者更简洁地说
{{ $blogs[0]->title ?: '' }}
假设只有当$blogs
通过第一个if
时,控制流才会到达那里。如果问题仍然存在,则问题在代码IMHO中的其他地方。您只需使用data\u 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"
>>>
因此,在这种情况下:
{{ data_get($blogs[0], 'title', '') }}
data_get()
将同时作用于数组和对象,返回第二个参数中定义的键或属性(可以是laravel.dot.notation.style
,也可以只是一个数组),如果对象/数组或键/属性不存在,则第三个参数将是默认返回值,默认值为null
编辑:
刚才看到了关于为什么原始代码不起作用的额外解释的请求
传递给视图的数组/集合上根本不存在索引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使用的是blade还是default
,它都不会进入三元语句,因为$blogs
上缺少0索引
按要求编辑2:
因此,出现未定义偏移量:x
错误的原因是PHP计算代码的顺序
Blade的或default
在幕后不过是一个三元语句:
return preg_replace('/^(?=\$)(.+?)(?:\s+or\s+)(.+?)$/si', 'isset($1) ? $1 : $2', $value);
因此,这将使:
isset($blogs[0]->title) ? $blogs[0]->title : ''
isset()
将检查对象上的标题是否已设置,但要执行此操作,将要求$blogs[0]
为有效对象。为此,它将尝试从索引0处的$blogs
数组中获取对象。但由于该索引不存在,它将触发异常,并带有未定义的偏移量:0
为了使用Blade的或默认值,您首先必须确保定义了$blogs[0]
(最好还要检查它是否是一个对象,否则您将得到“尝试获取非对象错误”属性,请注意,这不应该是视图的责任),之后,您可以像其他任何时候一样使用或default
@if (isset($blogs[0]) && is_object($blogs[0]))
{{ $blogs[0]->title or '' }}
@else
// some other default placeholder
@endif
使用data\u get()
时,基本上会得到相同的偏移错误,因为索引0仍然不存在
{{ data_get($blogs[0], 'title', '') }} // Undefined offset: 0
你可以玩脏东西,然后这样做(这不会在任何地方通过任何代码审查,我根本不应该键入它,这只是为了举例说明。)
无论如何,使用data\u get()
您最终还是会做类似的事情,因为您需要确保$blogs[0]
是您可以使用的:
@if (isset($blogs[0]))
{{ data_get($blogs[0], 'title', '') }}
@else
// some other default placeholder
@endif
总之,最好的选择是而不是在您的视图中依赖这样的索引,这根本不是您的视图的责任
Blade的或default
在单个变量上运行良好,但在处理对象属性时,您只需确保(父)对象存在即可。我在控制器中这样做:
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
从PHP7开始,您可以使用空合并运算符?
检查三元条件:
@if($posts?? '')
@foreach($posts as $post)
<h1>$post->title</h1>
<p>$post->content</p>
@endforeach
@endif
这么说,这个解决方案行得通?如果是的话,我觉得没问题,只是你应该用三个括号({{{和}}}}})来防止解释HTML(XSS缺陷)。@christoptd仅在Laravel4.x,Laravel5ESC中使用
@if($posts?? '')
@foreach($posts as $post)
<h1>$post->title</h1>
<p>$post->content</p>
@endforeach
@endif
{{ $blogs && $blogs[0]->title ? $blogs[0]->title : '' }}