You can simply solve this with the data_get()
helper.
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: "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"
>>>
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.
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.
>>> $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
.
Edit 2 as requested:
So the reason you get the Undefined offset: x
error is because of the order in which PHP evaluates the code.
Blade's or default
is behind the scenes nothing more than a ternary statement:
return preg_replace('/^(?=\$)(.+?)(?:\s+or\s+)(.+?)$/si', 'isset($1) ? $1 : $2', $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
.
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.
@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($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:
@if (isset($blogs[0]))
{{ data_get($blogs[0], 'title', '') }}
@else
// some other default placeholder
@endif
Bottomline, the best option would be not to 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.