php 如何在 Laravel 中处理未定义的偏移量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29588597/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to handle Undefined Offset in laravel?
提问by vs_lala
I am getting this error when I land on the page after logging in:
登录后登陆页面时出现此错误:
ErrorException in compiled.php line 11573: Undefined offset: 0 (View: C:\xampp\htdocs\campusguru\resources\views\home.blade.php)
在compiled.php line 11573中的ErrorException: Undefined offset: 0 (View: C:\xampp\htdocs\campusguru\resources\views\home.blade.php)
I know that the cause of this error is the empty variable that I passed to the view.
我知道这个错误的原因是我传递给视图的空变量。
I have already tried:
我已经尝试过:
if(isset($blog)) { do something }
and in blade view as:
并在刀片视图中为:
{{ $blogs[0]->title or '' }}
Is there anyway I could handle this error. Or is there a better way of doing it?
无论如何我可以处理这个错误。或者有更好的方法吗?
回答by iisurge
try the following:
尝试以下操作:
{{ isset($blogs[0]) ? $blogs[0]->title : '' }}
If your using a foreach to get every $blog->title use
如果您使用 foreach 来获取每个 $blog->title 使用
@foreach ($blogs as $blog)
{{ $blog->title }}
@endforeach
回答by Desh901
The problem is that $blogs
is actually defined and its value is []
(i.e. empty array
) so it means that isset($blogs)
statement will evaluate to true
. Same thing is valid for collections. If a collection is empty (i.e. has no elements but it's defined) isset($blogs)
will still evaluate to true
but accessing $blogs[0]
will cause an Undefined offset: 0
error.
问题是$blogs
实际上已定义并且其值为[]
(即空array
),因此这意味着该isset($blogs)
语句将评估为true
。同样的事情对集合有效。如果集合为空(即没有元素但已定义)isset($blogs)
仍将评估为,true
但访问$blogs[0]
将导致Undefined offset: 0
错误。
You could try the following solutions:
您可以尝试以下解决方案:
Using count
使用 count
if(count($blogs)) { /* do something */ }
if $blogs = []
or $blogs = null
the function count
will return zero so that means that $blogs
is empty.
if$blogs = []
或$blogs = null
函数count
将返回零,这意味着它$blogs
是空的。
Using empty
使用 empty
if(!empty($blogs)) { /* do something */ }
This is the equivalent of writing !isset($var) || $var == false
as described in the PHP Manual - empty:
这相当于PHP 手册中!isset($var) || $var == false
描述的写法- empty:
Returns FALSEif var exists and has a non-empty, non-zero value. Otherwise returns TRUE.
The following things are considered to be empty:
""
(an empty string)0
(0 as an integer)0.0
(0 as a float)"0"
(0 as a string)NULL
FALSE
array()
(an empty array)$var;
(a variable declared, but without a value)
如果 var 存在且具有非空、非零值,则返回FALSE。否则返回TRUE。
以下内容被认为是空的:
""
(空字符串)0
(0 作为整数)0.0
(0 作为浮点数)"0"
(0 作为字符串)NULL
FALSE
array()
(一个空数组)$var;
(声明的变量,但没有值)
Checking if a collection is empty
检查集合是否为空
If $blogs
is a Collection
is sufficient to check if it is not empty using `isNotEmpty()method:
If $blogs
is aCollection
足以使用`isNotEmpty()方法检查它是否为空:
@if($blogs->isNotEmpty()) <!-- Do your stuff --> @endif
EDIT
编辑
I forgot to add the blade syntax:
我忘了添加刀片语法:
@if(count($blogs)) <!-- Do whatever you like --> @endif
or
或者
@if(!empty($blogs)) <!-- Do whatever you like --> @endif
EDIT 2
编辑 2
I'm adding more content to this answer in order to address some of the issues presented in the comments. I think that your problem is the following:
我正在为此答案添加更多内容,以解决评论中提出的一些问题。我认为你的问题如下:
$blogs
is an empty collection, so it's defined but it has no elements. For this reason the if(isset($blogs))
statement will evaluate to true
passing the first if
condition. In your blade template you are making the check {{ $blogs[0]->title or '' }}
that is absolutely not equal to<?php isset($blogs[0]->title) ? $blogs[0]->title : '' ?>
as pointed out in the comments, but it is an expression that will return true
or false
, so it will never print out title
parameter even if $blogs[0]
exists. The problem here is that when checking the condition $blogs[0]->title
you are actually accessing the element 0
of the $blogs
collection that will trigger the exception Undefined offset: 0
because the collection is actually empty. What i was saying is that in addition to the
$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 */ }
(that checks that $blogs
is set and that it's length is greater than 0
) in your template you should do
(检查$blogs
已设置并且它的长度大于0
)在您的模板中您应该做
{{ isset($blogs[0]->title) ? $blogs[0]->title : '' }}
or more concisely
或者更简洁
{{ $blogs[0]->title ?: '' }}
assuming that the control flow will arrive there only if the $blogs
passed the first if
. If the issue still persists the problem is elsewhere in your code IMHO.
假设控制流只有在$blogs
通过第一个if
. 如果问题仍然存在,恕我直言,问题出在您的代码中的其他地方。
回答by Robert
You can simply solve this with the data_get()
helper.
您可以使用data_get()
助手简单地解决此问题。
For example:
例如:
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"
>>>
So in this case:
所以在这种情况下:
{{ data_get($blogs[0], 'title', '') }}
data_get()
will work both on arrays and objects, returning the key or attribute defined in the second param (this can be laravel.dot.notation.style
, or just an array), the 3rd param will be the default return value if the object/array or the key/attribute does not exist, the default is null.
data_get()
将适用于数组和对象,返回在第二个参数中定义的键或属性(这可以是laravel.dot.notation.style
,或只是一个数组),如果对象/数组或键/属性没有,则第三个参数将是默认返回值存在,默认为空。
Edit:
编辑:
Just saw the request for the extra explanation on why the original code wasn't working.
刚刚看到关于为什么原始代码不起作用的额外解释的请求。
Index 0 simply does not exist on the array/collection that is passed to the view.
传递给视图的数组/集合上根本不存在索引 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"
It doesn't matter if OP used the blade or default
, it doesn't even make it to the ternary statement because of the missing 0 index on $blogs
.
如果 OP 使用了 Blade 并不重要or default
,它甚至没有进入三元语句,因为缺少 0 索引$blogs
。
Edit 2 as requested:
根据要求编辑 2:
So the reason you get the Undefined offset: x
error is because of the order in which PHP evaluates the code.
所以你得到Undefined offset: x
错误的原因是因为 PHP 评估代码的顺序。
Blade's or default
is behind the scenes nothing more than a ternary statement:
Blade'sor default
在幕后无非是一个三元声明:
return preg_replace('/^(?=$)(.+?)(?:\s+or\s+)(.+?)$/si', 'isset() ? : ', $value);
So this will make:
所以这将使:
isset($blogs[0]->title) ? $blogs[0]->title : ''
isset()
will check if title on the object is set, but to do so, it will require $blogs[0]
to be a valid object. In order to do that, it will try and get the object from the $blogs
array at index 0. But since this index does not exist, it will trigger the Exception with an Undefined offset: 0
.
isset()
将检查是否设置了对象上的标题,但要这样做,它需要$blogs[0]
是一个有效的对象。为了做到这一点,它会尝试从$blogs
索引 0处的数组中获取对象。但由于该索引不存在,它将触发 Exception 异常Undefined offset: 0
。
In order to make this work with Blade's or default
, you would first have to ensure that $blogs[0]
is defined (and preferably also check that it's an object, otherwise you'll get the trying to get property of non-object error, please note that this should not be the responsibility of the view), after that you would be able to use the or default
as you would any other time.
为了使这个与 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
Basically you will get the same offset error when using data_get()
, because index 0 still does not exist.
基本上你会在使用时得到相同的偏移错误data_get()
,因为索引 0 仍然不存在。
{{ data_get($blogs[0], 'title', '') }} // Undefined offset: 0
You could play dirty and do this (this would not pass any code review anywhere and I should not have typed this at all, this is just to illustrate)
你可以玩得很脏然后这样做(这不会在任何地方通过任何代码,我根本不应该输入这个,这只是为了说明)
{{ data_get($blogs, '0.title', '') }} // Will display '' as it will check if key 0 exists
Anyway, with data_get()
you would still end up doing something like this, as you would need to make sure $blogs[0]
is something you can work with:
无论如何,data_get()
你最终还是会做这样的事情,因为你需要确保$blogs[0]
你可以使用:
@if (isset($blogs[0]))
{{ data_get($blogs[0], 'title', '') }}
@else
// some other default placeholder
@endif
Bottomline, the best option would be notto rely on indexes like this in your view, this is simply not the responsibility of your view.
底线,最好的选择是不要在您的视图中依赖这样的索引,这根本不是您的视图的责任。
Blade's or default
works perfectly on single variables, but when dealing with object attributes, you would just have to make sure the (parent) object exists when doing so.
Bladeor default
可以完美地处理单个变量,但是在处理对象属性时,您只需确保(父)对象存在即可。
回答by John
I do this way in controller:
我在控制器中这样做:
if (empty($allFares) || count($allFares)==0){
return back()->withError('No Fare Found For The City!');
}
OR in blade:
或在刀片中:
@if (!empty($allFares) || count($allFares)>0)
@foreach(allFares as $key=>$value)
@endforeach
@endif
回答by Nino Korent
If you have an object that's passed to the view and let's say your data is "posts" which is being held inside an object like this: $obj->posts.
如果你有一个传递给视图的对象,假设你的数据是“posts”,它被保存在这样的对象中:$obj->posts。
If you then go and do a foreach loop which would iterate trough every post and print out its parameters like in the example below it works perfectly well when you actually have posts.
如果你然后去做一个 foreach 循环,它会遍历每个帖子并打印出它的参数,就像下面的例子一样,当你真正有帖子时,它运行得非常好。
@foreach($obj->posts as $post)
<h1>$post->title</h1>
<p>$post->content</p>
@endforeach
Before doing the loop you'd want to check if attribute has been set with values. You can use isset() for this, and since it's a special form it can be used as isset($obj->posts) or isset($obj->posts[0]). The difference is that the latter will only check if the array key has any value so if your index key is anything but 0, it'll return false. For instance you have:
在执行循环之前,您需要检查是否已使用值设置属性。您可以为此使用 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
The way I'd make the check is the following:
我进行检查的方式如下:
@if(isset($obj->posts))
@foreach($obj->posts as $post)
...
@endoforeach
@endif
回答by Haritsinh Gohil
As of PHP7 you can use null coalescing operator ??
for checking ternary conditions:
从 PHP7 开始,您可以使用空合并运算符??
来检查三元条件:
@if($posts?? '')
@foreach($posts as $post)
<h1>$post->title</h1>
<p>$post->content</p>
@endforeach
@endif
And if you want to print any variable directly then check first that the variable exists or not in condition, so you can do as below:
如果您想直接打印任何变量,则首先检查该变量是否存在,因此您可以执行以下操作:
{{ $blogs && $blogs[0]->title ? $blogs[0]->title : '' }}