Have you ever wondered what's the difference between !$var
and is_null($var)
? What about isset($var)
? Let's discuss those with a practical example.
Let's jump into an example function that takes four different arguments and returns HTML text.
All those parameters are optional, so inside the function, we're checking if they are passed or not with the !
operator.
function formatUser( ?User $user, ?bool $isVip, ?string $nickname, ?array $badges): string { $user = ! $user ? 'No email present.' : $user->email; $isVip = ! $isVip ? '' : 'checked'; $nickname = ! $nickname ? 'Anonymous' : $nickname; if (! $badges) { $badges = ['Not assigned']; } $formattedBadges = ''; foreach ($badges as $badge) { $formattedBadges .= '<div class="badge">' . $badge . '</div>'; } return sprintf('<div class="user-row"> <div>%s</div> <div>VIP <input type="checkbox" disabled %s></div> <div>%s</div> <div class="flex space-x-0.5">%s</div> </div>', $user, $isVip, $nickname, $formattedBadges );}
And then, we're trying to use that function with four different cases. The Blade View part of using that function looks like this:
<div class="p-6 text-gray-900"> {!! formatUser(User::find(1), true, fake()->words(asText: true), null) !!} {!! formatUser(User::find(2), false, null, null) !!} {!! formatUser(User::find(3), false, '0', null) !!} {!! formatUser(null, true, 'Some nickname', ['Category Z', 'Category A']) !!}</div>
And this is the result.
At first glance, everything looks good, but can you spot the mistake?
Right, the third entry should be 0
and not 'Anonymous?' The nickname "0" technically is valid, right? Then what went wrong?
Global table of operators
To understand that, let's look up the second column on the negation of this table.
As you can see, using the !
operation, both integer 0
and string '0'
values are considered equal to false,
after negation, they become true
, which is not what we intended to do.
If not "!", then what?
When checking strings or integers for null values, it is better to avoid loose operations and use strict === null
or is_null
checks are equivalent. In the same way, strictly not !== null
and isset()
statements are identical too.
In our specific case, we can ignore what happens with other types because the nickname argument will always be null
or string
; even if we pass an integer 0
, it will become a string '0'
because of the type hint.
function formatUser( ?User $user, ?bool $isVip, ?string $nickname, ?array $badges): string {
We can safely use loose comparison ==,
and empty string ''
value will also be treated as not present, which is reasonable in this scenario.
$nickname = $nickname == null ? 'Anonymous' : $nickname;
Now, what about checking arrays or models for being empty?
Checking Non-Existing Array Keys
So why do we have empty()
and isset()
methods? We can not easily avoid them when working with non-existing array keys. They do not throw an Exception when accessing an undefined array key, so we can safely check for key or value presence in the array.
Checking For Model Presence
Working with Eloquent is relatively straightforward. Methods like find()
and first()
are consistent and always return null
if the record is not found. Objects are always evaluated to be true.
The same table applies when using the ->first()
method.
User::where(...)->something()->first();
No comments or questions yet...