Photo by Aakash Dhage on Unsplash
Introduction
In PHP, I often see the ternary operator (?:) and null coalescing operator (??) being used interchangeably, but they actually serve different purposes.
In this article, we'll explore what both of these operators do and how they differ. We'll also look at some common gotchas that developers (myself included) have run into when using these operators.
The Ternary Operator (?:) in PHP
The ternary operator is a shorthand way of writing a ternary conditional statement.
For example, let's take a traditional if-else statement. We'll keep the examples in this article super simple purely for brevity.
Imagine we're trying to set a display name based on a provided name in a payload:
// Imagine this payload comes from an HTTP request.
$payload = [
'name' => 'Ash',
// ...
];
if ($payload['name']) {
$displayName = $payload['name'];
} else {
$displayName = 'Guest';
}
// $displayName is now set to 'Ash'
We can rewrite this using a ternary condition like so:
$payload = ['name' => 'Ash'];
$displayName = $payload['name'] ? $payload['name'] : 'Guest'; // 'Ash'
Which can then be further shortened using the ?: operator:
$payload = ['name' => 'Ash'];
$displayName = $payload['name'] ?: 'Guest'; // 'Ash'
Now let's look at some examples of what $displayName would be set to based on different values of $payload['name'].
If the payload contains a non-empty string:
$payload = ['name' => 'Ash'];
$displayName = $payload['name'] ?: 'Guest'; // 'Ash'
If the request payload contains an empty string or null:
$payload = ['name' => ''];
$displayName = $payload['name'] ?: 'Guest'; // 'Guest'
If the payload contains null:
$payload = ['name' => null];
$displayName = $payload['name'] ?: 'Guest'; // 'Guest'
If the payload contains false:
$payload = ['name' => false];
$displayName = $payload['name'] ?: 'Guest'; // 'Guest'
However, what would happen if the payload array didn't have a name key at all?
$payload = [];
$displayName = $payload['name'] ?: 'Guest';
Running the above code would result in the following exception being thrown:
ErrorException: Undefined array key "name"
So we can see that the ternary operator checks for "truthiness" of the value. If the value is falsy (such as an empty string or null), it returns the value on the right side of the operator.
However, if the variable is not set at all, it will throw an error. And this is where I often see people get confused between the ?: and ?? operators. I've seen many developers expect that the ?: operator would handle unset variables gracefully, but it does not. So let's check out the null coalescing operator next.
The Null Coalescing Operator (??) in PHP
The null coalescing operator works in a similar way to the ternary operator, but it allows us to handle unset variables without throwing an error.
Let's take our previous example and update it to use the ?? operator instead:
$payload = ['name' => 'Ash'];
$displayName = $payload['name'] ?? 'Guest'; // 'Ash'
The above code example is essentially the shorthand form of:
$payload = ['name' => 'Ash'];
$displayName = isset($payload['name']) ? $payload['name'] : 'Guest'; // 'Ash'
As we can see, we can use the ?? operator in a similar way to the ?: operator, but it's checking whether the variable is set or not, rather than checking for "truthiness".
Let's see what happens if we try to access the name key when it is not set:
$payload = [];
$displayName = $payload['name'] ?? 'Guest'; // 'Guest'
In the code example, we can see that when the name key is not set in the payload array, the ?? operator returns the value on the right side of the operator without throwing an error.
This can be really useful when working with data that's passed to you from external sources, such as API requests or user input, where you can't always guarantee that certain keys will be present.
Another key difference between the ?? and ?: operators is that the ?? operator only checks for null or unset values, whereas the ?: operator checks for "truthiness". Let's take this example:
$payload = ['name' => false];
// Using the ternary operator:
$displayName = $payload['name'] ?: 'Guest'; // 'Guest'
// Using the null coalescing operator:
$displayName = $payload['name'] ?? 'Guest'; // false
As we can see in the example above, when the name key is set to false, the ?: operator returns 'Guest', whereas the ?? operator returns false. This is something you'll want to keep in mind when deciding which operator to use.
Common Gotcha with the Null Coalescing Operator
A common gotcha I see developers run into (and have done myself many times) is accidentally hiding errors when using the ?? operator.
For example, let's say you have an API request payload that is expected to contain a first_name key, but you accidentally misspell it as frist_name:
$payload = ['first_name' => 'Ash'];
$firstName = $payload['frist_name'] ?? 'Guest'; // 'Guest'
At first glance, this code might seem okay since it doesn't throw any runtime errors. However, we will always get 'Guest' as the value of $firstName. Of course, this should typically be caught during manual and automated testing. But these things can sometimes slip through the cracks, especially in larger codebases.
Alternatively, if we had used the ternary operator instead, we would have gotten an error when trying to access the unset first_name key, which would have alerted us to the typo:
$payload = ['first_name' => 'Ash'];
$firstName = $payload['frist_name'] ?: 'Guest';
// ErrorException: Undefined array key "first_name"
Should You Use the Ternary or Null Coalescing Operator?
Both operators have valid use cases and are valuable tools in your PHP arsenal.
If you always know that a value will be available (i.e. it won't be unset), and you want to check for "truthiness", then the ternary operator (?:) is a good choice.
However, if you want to handle unset variables gracefully, or you only want to check for null or unset values, then the null coalescing operator (??) might be the better option.
As you'd imagine, the decision of which operator to use often comes down to the specific use case and the data you're working with. So you'll likely use a mixture of both operators in your codebase.
Conclusion
In this article, we've quickly explored the differences between the ?: (ternary) and ?? (null coalescing) operators in PHP.
If you enjoyed reading this post, you might be interested in checking out my 220+ page ebook "Battle Ready Laravel" which covers similar topics in more depth.
Or, you might want to check out my other 440+ page ebook "Consuming APIs in Laravel" which teaches you how to use Laravel to consume APIs from other services.
If you're interested in getting updated each time I publish a new post, feel free to sign up for my newsletter.
Keep on building awesome stuff! 🚀
Other articles you might like
Immutable and Mutable Dates in PHP
Introduction When working with dates in PHP, it's important to understand the difference between mut...
Email Utilities for Laravel v1.0 Released!
Introduction A common feature I often need to build for public-facing forms is to prevent users from...
Laravel 12 How to Change Date Format Example
In this laravel tutorial titled “laravel 12 how to change date format example”, you’ll learn differe...
The Laravel portal for problem solving, knowledge sharing and community building.