Firstly, let's understand what the different elements are doing:
isset
takes a variable, array element, etc, and returns true if it exists, and has any value other than null
empty
takes a variable, array element, etc, and returns false if it exists, and has any value which would be considered equivalent to true
??
examines a variable, array element, etc, and returns its value if it exists, and has any value other than null; otherwise, it returns its right-hand argument
- any expression used in an
if
statement is cast to boolean automatically
So, we can look at the equivalences:
empty
is a combination of isset()
and a cast to false; specifically, empty($a) === !isset($a) || !(bool)$a
, so !empty($a) === isset($a) && (bool)$a
??
uses the same check as isset
, not the same check as empty
; so $a ?? false
on its own is equivalent to isset($a) ? $a : false
- but, in an
if
statement, the whole thing will be forced to boolean, so if ( $a ?? false ) ...
is equivalent to if ( (bool)(isset($a) ? $a : false) ) ...
or more readably if ( isset($a) ? (bool)$a : false ) ...
Which brings us to the answer, which is that the following all do the same thing:
if ( isset($a) && !empty($a) ) ...
if ( isset($a) && !(bool)$a ) ... // empty() is just a bool cast + isset
if ( !empty($a) ) ... // the isset is actually redundant
if ( isset($a) ? (bool)$a : false ) ... // same logic as the && version
if ( (bool)($a ?? false) ) ... // ?? does the isset for us
if ( $a ?? false ) ... // if does the (bool) for us
Probably the most readable is just to use !empty($a)
on its own, and leave ??
for where you actually need the original value rather than a true
.