Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

kokoshneta's avatar

How to get collections to play nicely with null coalescing operator

The null coalescing operator ?? available since PHP 7.0 “returns its first operand if it exists and is not null; otherwise it returns its second operand”. This works more or less everywhere you can think of to use it:

echo $nonexistent ?? 'a'; // outputs 'a'
echo $nonexistent[5] ?? 'b' // outputs 'b'
echo $nonexistent['hello'] ?? 'c' // outputs 'c'
echo $nonexistent->evenMoreNonexistent ?? 'd' // outputs 'd'

The only place it doesn’t work is if you try to use it with a nonexistent function/method, or a method on a variable that either doesn’t exist or is not an object:

$int = 5;
echo $int->stillNotHere() ?? 'e'; // throws exception
echo $nonexistent->allInYourMind() ?? 'f'; // throws exception

Unfortunately, due to all the fancy magic method stuff that happens in Laravel collections (or at least I’m assuming that’s why), attempting to access a nonexistent property on a collection object behaves sort of like a method call, in that it will throw an exception instead of returning NULL, which means the null coalescing operator won’t work:

$users = User::all();
echo $users->nonexistent ?? 'g'; // throws exception

Is there a (reasonably simple) way to get around this and make collection properties behave more like regular object properties?

(I know there are plenty ways to work around it using empty() and similar strategies, but I’m specifically looking for a way to transparently make collections work with the null coalescing operator.)

0 likes
3 replies
Snapey's avatar
Snapey
Best Answer
Level 122

Your example is not really typical use since what you have is a collection of user models as an array.

This works as expected

$users->first()->nonexistant ?? 'g';

but in the spirit of your question, you can use the optional helper

optional($users)->nonexistant ?? 'g';
1 like
kokoshneta's avatar

@Snapey Using User::all() was just a hyper-simplistic way to create something that’s visibly a collection for the example code, not related to any actual code. And yeah, I know Laravel collections aren’t meant to have properties of their own – even if I think that’s a silly design decision.

But I am specifically talking about referencing potentially nonexistent property on the collection itself, not on the objects in the collection.

For example, say you have a collection of products which you then group by category, so you end up with a collection of collections, where each inner collection represents a category of products. It often makes sense to add a property such as categoryName to the inner collections and then that property as a header when rendering your view. But that view may also be used for displaying products that are grouped by some other logic, one where it doesn’t make sense to have category names as headers. In such cases, you’d maybe do the headers something like this:

@foreach ($outerCollection as $innerCollection)
	<h1>{{ $innerCollection->categoryName ?? $fallbackHeader }}</h1>

	@foreach ($innerCollection as $product)
		// do stuff
	@endforeach
@endforeach

If collections were more ‘normal’, that would work exactly as expected, instead of throwing an exception if there’s no categoryName property on an inner collection.

kokoshneta's avatar

@Snapey Ah, I was typing while you updated your answer!

optional() does precisely what I was looking for – excellent!

Please or to participate in this conversation.