Forum Moderators: coopster

Message Too Old, No Replies

Difference between ? and ?:

         

csdude55

4:46 am on Jan 21, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I'm not sure that I get the difference here.

If I understand correctly, I can use $foo = $foo ?: $bar; in lieu of $foo = $foo ? $foo : $bar;. Both mean "if $foo exists return $foo, else return $bar".

But doesn't $foo = $foo ? $bar; do the same thing?

NickMNS

5:42 am on Jan 21, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Not sure about the specifics of PHP, but I think you may have made a typo:
$foo = $foo ? $bar

did you mean
$foo = $foo ? $bar


based on the logic of Javascript
Which I assume would be the equivalent in JS of:
 foo = foo ? bar 

where ? is the Nullish coalescing operator
This would return foo = foo when foo is true or false but foo = bar when foo is null or undefined.
Based on a quick search of the PHP docs this appears to be the same in both languages.

Side note: Is it just me or are the PHP docs a total mess... I mean compared to the mozzilla docs for JS. Horrible....

csdude55

5:48 am on Jan 21, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Hmm, it looks like the site is auto-fixing what it thinks is a typo. I'm trying to put 2 question marks in a row...

Lemme try this:

$foo = $foo ? $foo : $bar;
$foo = $foo ?: $bar;
$foo = $foo ?? $bar;

And yes, I've choked on the PHP docs a million times!

phranque

8:11 am on Jan 21, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



yes you will need to insert some null bbcode between the ?s to avoid having consecutive ?s folded into one.

JorgeV

9:53 am on Jan 21, 2021 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member Top Contributors Of The Month



Hello,

$foo = $foo ? $foo : $bar;
$foo = $foo ?: $bar;

Those two lines , are the same. ?: is a shorthand.

It means if $foo is not NULL, 0 (the number zero), or an empty string, then to give $foo the value of $bar.

If $foo does not exist, you will have a Notice error in your logs, saying "Undefined variable: foo" and $bar will be returned.

As for :
$foo = $foo ?? $bar; 

It means, if $foo does not exist, or is equal to NULL, then return $bar, otherwise, get the value of $foo. If $foo equals zero or is en empty string, this is zero or this empty string which is returned.

In that case, you do not have Notice error in the log. This is the purpose of the ?? operator.

Before PHP 7, you needed to do:
$foo = isset($foo) ? $foo : $bar

NickMNS

1:15 pm on Jan 21, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Yup I feel kind of silly read this again this morning... I should have preview my post. But I think we understand each other.
@JorgeV
It means if $foo is not NULL, 0 (the number zero), or an empty string, then to give $foo the value of $bar.

While what you describe is accurate it is not complete. It means if $foo is "false" then $foo will = $bar. That includes any value that resolves to false, such as 0, empty string, or false. I'm not sure how PHP handles NULL, undefined and NaN, but in JS these are all falsy.

The ?? operator is explicit to null values, specifcally NULL and undefined. So if $foo == false, $foo will remain unchanged, but if $foo is undefined then $foo will be assigned $bar. The difference is subtle and I guess only comes into play if you are dealing will boolean values.

...previewing post...
All is fine.

csdude55

3:38 pm on Jan 21, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I gotcha. So I should use ?? if I'm checking if the pattern is also set; otherwise, use ?:

csdude55

3:58 pm on Jan 21, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Addendum, I just discovered that ?? apparently doesn't wrap other functions. Eg, these are not the same:

$foo = (isset($foo) && is_numeric($foo)) ?? false;
$foo = is_numeric($foo) ?? false;

Which makes perfect sense, since the return from is_numeric() is true or false, not the value of $foo.

But this works:

$foo = is_numeric($foo ?? false);

csdude55

8:50 pm on Jan 25, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Slight tangent, and this is probably old news to some people, but this also appears to work fine and saves a few bytes:

// original
if (isset($foo) && $foo === 'bar') { ... }

// shortened
if (($foo ?? false) === 'bar') { ... }

robzilla

9:08 pm on Jan 25, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



At the expensive of readability, I would say. isset() being much easier to read than ($foo ? false).

Hard to say if bytes are actually saved in the opcode.

csdude55

9:23 pm on Jan 25, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I don't know why, @robzilla, but my eyes go crossed every time I try to use isset()! LOL Maybe it's because I'm expecting it to be is_set(), instead? But for whatever reason, it's easier for me to read ($foo ?? false).

Note: I originally said something about benchmark speeds, but my test was wrong so forget I said that... speed wise, they're essentially the same.

Dimitri

11:04 pm on Jan 25, 2021 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member Top Contributors Of The Month



isset is a function, and ?? is a build-in language instruction. A function call will always be slower.

Now, in real life situation, you will not see the difference. It makes no sense to benchmark such code, by executing it thousands or millions of times, since this is not going to happen in you real script.

robzilla

10:30 am on Jan 26, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



isset is a function, and ? is a build-in language instruction. A function call will always be slower.

It is in PHP, but that's translated to C, and I'm not sure C has a null-coalescing operator. It may be translated to a function in C, so it's hard to say.

But for whatever reason, it's easier for me to read ($foo ? false).

Fair enough!

w3dk

1:55 pm on Jan 26, 2021 (gmt 0)

10+ Year Member Top Contributors Of The Month




Addendum, I just discovered that ? apparently doesn't wrap other functions. Eg, these are not the same:


$foo = (isset($foo) && is_numeric($foo)) ? false;
$foo = is_numeric($foo) ? false;


Which makes perfect sense, since the return from is_numeric() is true or false, not the value of $foo.


Not quite sure what you mean been this? These are "the same", in that the resulting value of $foo is the same, except the second will trigger an E_NOTICE if $foo is initially undefined, because you are passing an undefined var to the is_numeric() function - this is not directly related to the null coalescing operator.



// original
if (isset($foo) && $foo === 'bar') { ... }

// shortened
if (($foo ? false) === 'bar') { ... }



Although I would avoid these constructs entirely and ensure all variables are declared/initialised early (in one place). After all, it is rare that you'd only need to reference a variable once.

isset is a function, and ? is a build-in language instruction.


isset() is also a built-in language construct. (This allows it to bypass the normal error handling.)

It is in PHP, but that's translated to C, and I'm not sure C has a null-coalescing operator. It may be translated to a function in C, so it's hard to say.


PHP might be written in C and call C libraries/functions, but it's not "translated to C".