PHP Operators ?? vs ?: [duplicate] - php

Can someone explain the differences between ternary operator shorthand (?:) and null coalescing operator (??) in PHP?
When do they behave differently and when in the same way (if that even happens)?
$a ?: $b
VS.
$a ?? $b

When your first argument is null, they're basically the same except that the null coalescing won't output an E_NOTICE when you have an undefined variable. The PHP 7.0 migration docs has this to say:
The null coalescing operator (??) has been added as syntactic sugar
for the common case of needing to use a ternary in conjunction with
isset(). It returns its first operand if it exists and is not NULL;
otherwise it returns its second operand.
Here's some example code to demonstrate this:
<?php
$a = null;
print $a ?? 'b'; // b
print "\n";
print $a ?: 'b'; // b
print "\n";
print $c ?? 'a'; // a
print "\n";
print $c ?: 'a'; // Notice: Undefined variable: c in /in/apAIb on line 14
print "\n";
$b = array('a' => null);
print $b['a'] ?? 'd'; // d
print "\n";
print $b['a'] ?: 'd'; // d
print "\n";
print $b['c'] ?? 'e'; // e
print "\n";
print $b['c'] ?: 'e'; // Notice: Undefined index: c in /in/apAIb on line 33
print "\n";
The lines that have the notice are the ones where I'm using the shorthand ternary operator as opposed to the null coalescing operator. However, even with the notice, PHP will give the same response back.
Execute the code: https://3v4l.org/McavC
Of course, this is always assuming the first argument is null. Once it's no longer null, then you end up with differences in that the ?? operator would always return the first argument while the ?: shorthand would only if the first argument was truthy, and that relies on how PHP would type-cast things to a boolean.
So:
$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'
would then have $a be equal to false and $b equal to 'g'.

Ran the below on php interactive mode (php -a on terminal). The comment on each line shows the result.
var_export (false ?? 'value2'); // false
var_export (true ?? 'value2'); // true
var_export (null ?? 'value2'); // value2
var_export ('' ?? 'value2'); // ""
var_export (0 ?? 'value2'); // 0
var_export (false ?: 'value2'); // value2
var_export (true ?: 'value2'); // true
var_export (null ?: 'value2'); // value2
var_export ('' ?: 'value2'); // value2
var_export (0 ?: 'value2'); // value2
The Null Coalescing Operator ??
?? is like a "gate" that only lets NULL through.
So, it always returns first parameter, unless first parameter happens to be NULL.
This means ?? is same as ( !isset() || is_null() )
Use of ??
shorten !isset() || is_null() check
e.g $object = $object ?? new objClassName();
Stacking Null Coalese Operator
$v = $x ?? $y ?? $z;
// This is a sequence of "SET && NOT NULL"s:
if( $x && !is_null($x) ){
return $x;
} else if( $y && !is_null($y) ){
return $y;
} else {
return $z;
}
The Ternary Operator ?:
?: is like a gate that lets anything falsy through - including NULL
Anything falsy: 0, empty string, NULL, false, !isset(), empty()
Same like old ternary operator: X ? Y : Z
Note: ?: will throw PHP NOTICE on undefined (unset or !isset()) variables
Use of ?:
checking empty(), !isset(), is_null() etc
shorten ternary operation like !empty($x) ? $x : $y to $x ?: $y
shorten if(!$x) { echo $x; } else { echo $y; } to echo $x ?: $y
Stacking Ternary Operator
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 1 ?: 0 ?: 3 ?: 2; //1
echo 2 ?: 1 ?: 0 ?: 3; //2
echo 3 ?: 2 ?: 1 ?: 0; //3
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 0 ?: 0 ?: 2 ?: 3; //2
echo 0 ?: 0 ?: 0 ?: 3; //3
// Source & Credit: http://php.net/manual/en/language.operators.comparison.php#95997
// This is basically a sequence of:
if( truthy ) {}
else if(truthy ) {}
else if(truthy ) {}
..
else {}
Stacking both, we can shorten this:
if( isset($_GET['name']) && !is_null($_GET['name'])) {
$name = $_GET['name'];
} else if( !empty($user_name) ) {
$name = $user_name;
} else {
$name = 'anonymous';
}
To this:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
Cool, right? :-)

If you use the shortcut ternary operator like this, it will cause a notice if $_GET['username'] is not set:
$val = $_GET['username'] ?: 'default';
So instead you have to do something like this:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
The null coalescing operator is equivalent to the above statement, and will return 'default' if $_GET['username'] is not set or is null:
$val = $_GET['username'] ?? 'default';
Note that it does not check truthiness. It checks only if it is set and not null.
You can also do this, and the first defined (set and not null) value will be returned:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
Now that is a proper coalescing operator.

The major difference is that
Ternary Operator expression expr1 ?: expr3 returns expr1 if expr1 evaluates to
TRUE but on the other hand Null Coalescing Operator expression (expr1) ?? (expr2)
evaluates to expr1 if expr1 is not NULL
Ternary
Operator expr1 ?: expr3 emit a notice if the left-hand side
value (expr1) does not exist but on the other hand Null Coalescing Operator (expr1) ?? (expr2) In particular, does not emit a notice if the left-hand side value (expr1) does
not exist, just like isset().
TernaryOperator is left associative
((true ? 'true' : false) ? 't' : 'f');
Null Coalescing Operator is right associative
($a ?? ($b ?? $c));
Now lets explain the difference between by example :
Ternary Operator (?:)
$x='';
$value=($x)?:'default';
var_dump($value);
// The above is identical to this if/else statement
if($x){
$value=$x;
}
else{
$value='default';
}
var_dump($value);
Null Coalescing Operator (??)
$value=($x)??'default';
var_dump($value);
// The above is identical to this if/else statement
if(isset($x)){
$value=$x;
}
else{
$value='default';
}
var_dump($value);
Here is the table that explain the difference and similarity between '??' and ?:
Special Note : null coalescing operator and ternary operator is an
expression, and that it doesn't evaluate to a variable, but to the
result of an expression. This is important to know if you want to
return a variable by reference. The statement return $foo ?? $bar; and
return $var == 42 ? $a : $b; in a return-by-reference function will
therefore not work and a warning is issued.

Both of them behave differently when it comes to dynamic data handling.
If the variable is empty ( '' ) the null coalescing will treat the variable as true but the shorthand ternary operator won't. And that's something to have in mind.
$a = NULL;
$c = '';
print $a ?? '1b';
print "\n";
print $a ?: '2b';
print "\n";
print $c ?? '1d';
print "\n";
print $c ?: '2d';
print "\n";
print $e ?? '1f';
print "\n";
print $e ?: '2f';
And the output:
1b
2b
2d
1f
Notice: Undefined variable: e in /in/ZBAa1 on line 21
2f
Link: https://3v4l.org/ZBAa1

Both are shorthands for longer expressions.
?: is short for $a ? $a : $b. This expression will evaluate to $a if $a evaluates to TRUE.
?? is short for isset($a) ? $a : $b. This expression will evaluate to $a if $a is set and not null.
Their use cases overlaps when $a is undefined or null. When $a is undefined ?? will not produce an E_NOTICE, but the results are the same. When $a is null the result is the same.

For the beginners:
Null coalescing operator (??)
Everything is true except null values and undefined (variable/array index/object attributes)
ex:
$array = [];
$object = new stdClass();
var_export (false ?? 'second'); # false
var_export (true ?? 'second'); # true
var_export (null ?? 'second'); # 'second'
var_export ('' ?? 'second'); # ""
var_export ('some text' ?? 'second'); # "some text"
var_export (0 ?? 'second'); # 0
var_export ($undefinedVarible ?? 'second'); # "second"
var_export ($array['undefined_index'] ?? 'second'); # "second"
var_export ($object->undefinedAttribute ?? 'second'); # "second"
this is basically check the variable(array index, object attribute.. etc) is exist and not null. similar to isset function
Ternary operator shorthand (?:)
every false things (false,null,0,empty string) are come as false, but if it's a undefined it also come as false but Notice will throw
ex
$array = [];
$object = new stdClass();
var_export (false ?: 'second'); # "second"
var_export (true ?: 'second'); # true
var_export (null ?: 'second'); # "second"
var_export ('' ?: 'second'); # "second"
var_export ('some text' ?? 'second'); # "some text"
var_export (0 ?: 'second'); # "second"
var_export ($undefinedVarible ?: 'second'); # "second" Notice: Undefined variable: ..
var_export ($array['undefined_index'] ?: 'second'); # "second" Notice: Undefined index: ..
var_export ($object->undefinedAttribute ?: 'second'); # "Notice: Undefined index: ..
Hope this helps

Scroll down on this link and view the section, it gives you a comparative example as seen below:
<?php
/** Fetches the value of $_GET['user'] and returns 'nobody' if it does not exist. **/
$username = $_GET['user'] ?? 'nobody';
/** This is equivalent to: **/
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
/** Coalescing can be chained: this will return the first defined value out of $_GET['user'], $_POST['user'], and 'nobody'. **/
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
?>
The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.
Essentially, using the coalescing operator will make it auto check for null unlike the ternary operator.

The other answers goes deep and give great explanations. For those who look for quick answer,
$a ?: 'fallback' is $a ? $a : 'fallback'
while
$a ?? 'fallback' is $a = isset($a) ? $a : 'fallback'
The main difference would be when the left operator is either:
A falsy value that is NOT null (0, '', false, [], ...)
An undefined variable

It seems there are pros and cons to using either ?? or ?:. The pro to using ?: is that it evaluates false and null and "" the same. The con is that it reports an E_NOTICE if the preceding argument is null. With ?? the pro is that there is no E_NOTICE, but the con is that it does not evaluate false and null the same. In my experience, I have seen people begin using null and false interchangeably but then they eventually resort to modifying their code to be consistent with using either null or false, but not both. An alternative is to create a more elaborate ternary condition: (isset($something) or !$something) ? $something : $something_else.
The following is an example of the difference of using the ?? operator using both null and false:
$false = null;
$var = $false ?? "true";
echo $var . "---<br>";//returns: true---
$false = false;
$var = $false ?? "true";
echo $var . "---<br>"; //returns: ---
By elaborating on the ternary operator however, we can make a false or empty string "" behave as if it were a null without throwing an e_notice:
$false = null;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---
$false = false;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---
$false = "";
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---
$false = true;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: 1---
Personally, I think it would be really nice if a future rev of PHP included another new operator: :? that replaced the above syntax. ie:
// $var = $false :? "true"; That syntax would evaluate null, false, and "" equally and not throw an E_NOTICE...

class a
{
public $a = 'aaa';
}
$a = new a();
echo $a->a; // Writes 'aaa'
echo $a->b; // Notice: Undefined property: a::$b
echo $a->a ?? '$a->a does not exists'; // Writes 'aaa'
// Does not throw an error although $a->b does not exist.
echo $a->b ?? '$a->b does not exist.'; // Writes $a->b does not exist.
// Does not throw an error although $a->b and also $a->b->c does not exist.
echo $a->b->c ?? '$a->b->c does not exist.'; // Writes $a->b->c does not exist.

Practical short answer :
Try:
var_dump('' ?: 'ok');
vs
var_dump('' ?? 'ok');
The first one will return 'ok' if the tested value (or variable *) evaluates to false
whereas
The second one will return 'ok' if the tested value (or variable *) is null or not initialized/set.
*CAUTION : if you want to test a variable with ?:, you must first ensure it is initialized/set, otherwise PHP will raise an E_NOTICE (whereas ?? wont).

Null Coalescing operator performs just two tasks: it checks whether the variable is set and whether it is null. Have a look at the following example:
<?php
# case 1:
$greeting = 'Hola';
echo $greeting ?? 'Hi There'; # outputs: 'Hola'
# case 2:
$greeting = null;
echo $greeting ?? 'Hi There'; # outputs: 'Hi There'
# case 3:
unset($greeting);
echo $greeting ?? 'Hi There'; # outputs: 'Hi There'
The above code example states that Null Coalescing operator treats a non-existing variable and a variable which is set to NULL in the same way.
Null Coalescing operator is an improvement over the ternary operator. Have a look at the following code snippet comparing the two:
<?php /* example: checking for the $_POST field that goes by the name of 'fullname'*/
# in ternary operator
echo "Welcome ", (isset($_POST['fullname']) && !is_null($_POST['fullname']) ? $_POST['fullname'] : 'Mr. Whosoever.'); # outputs: Welcome Mr. Whosoever.
# in null coalecing operator
echo "Welcome ", ($_POST['fullname'] ?? 'Mr. Whosoever.'); # outputs: Welcome Mr. Whosoever.
So, the difference between the two is that Null Coalescing operator operator is designed to handle undefined variables better than the ternary operator. Whereas, the ternary operator is a shorthand for if-else.
Null Coalescing operator is not meant to replace ternary operator, but in some use cases like in the above example, it allows you to write clean code with less hassle.
Credits: http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples

When using the superglobals like $_GET or $_REQUEST you should be aware that they could be an empty string.
In this specal case this example
$username = $_GET['user'] ?? 'nobody';
will fail because the value of $username now is an empty string.
So when using $_GET or even $_REQUEST you should use the ternary operator instead like this:
$username = (!empty($_GET['user'])?$_GET['user']:'nobody';
Now the value of $username is 'nobody' as expected.

:? - means that if the first operand is true, it will return it. Otherwise, it will return the second one.
?? - evaluates if the first operand exists and is not null. If so, it returns it; otherwise, it returns its second operand.
I found an article that describes very nice the difference:
https://www.fparedes.com/blog/null-coalescing-vs-elvis-operator-php/

Related

Negated null coalescing operator (double question mark - ??)

I want to do this
if( !$result['success'] ?? false){
... //handle error case
But it doesn't work. Why not?
Workaround is this:
$isSuccess = $result['success'] ?? false;
if((!$isSuccess){
... //handle error case
Is there a better workaround?
Test to reproduce:
<?php
$a = [];
$x = !$a['x'] ?? 'bbb';
echo $x;
2 problems. Throws a notice. And: echos '1'
You can group the expression you're trying to negate.
if (!($result['success'] ?? false)) {
It's an operator precedence issue. The negation is of higher precedence than the null coalesce, so it is evaluated before.
So with the example $x = !$a['x'] ?? 'bbb';
We're saying "if !$a['x'] is null then 'bbb'". Well, $a['x'] is null, since it's undefined, but !$a['x'] isn't null, it is actually true (because !null === true), so the part of the expression after ?? is never evaluated.
You see 1 because that's the string representation of true.
If it was mine, I would write it instead as
if (empty($result['success'])) {
since empty will check for existence and truthiness simultaneously.

Getting literal expression value with OR operators instead of true or false in PHP [duplicate]

This question already has answers here:
Quickest PHP equivalent of javascript `var a = var1||var2||var3;` expression
(3 answers)
Closed 3 years ago.
In Javascript, we can conveniently get one of the various options that is offered in || operator. For example:
console.log('a' || '' || 0); // Yields 'a'
console.log(0 || 'b' || 'a'); // Yields 'b'
Those results above can easily be assigned to a variable like this:
let test = 'a' || '' || 0;
In PHP, though, when I try this:
$test = 'a' || '' || 0; gives me a $test = 1, with 1 meaning true. Is there a way in PHP to get the literal value of the expression which caused it to yield true?
You can use the Elvis operator for this purpose, e.g.
$test = 'a' ?: '' ?: 0;
var_dump($test);
> string(1) "a"
$test2 = 0 ?: 'b' ?: 'a';
var_dump($test2);
> string(1) "b"
There is also null coalescing operator (??) but it takes the second value only if the first is null, so e.g. 0 ?? 'a' will take 0 because it's not null.
Per some user-contributed comments on PHP's logical operators page, you can use the ternary operator:
$test = $a ? $a : ($b ? $b : 'default')
Or if you're running PHP 7+ and you only need to pass over null variables (rather than falsy variables) you can use the null-coalescing operator ??:
$test = $a ?? $b ?? 'default'
PHP's boolean operators always return a boolean value... as opposed
to other languages that return the value of the last evaluated
expression.
For example:
$a = 0 || 'avacado';
print "A: $a\n";
will print:
A: 1
in PHP -- as opposed to printing "A: avacado" as it would in a language like Perl or JavaScript.
This means you can't use the '||' operator to set a default value:
$a = $fruit || 'apple';
instead, you have to use the '?:' ternary operator:
$a = ($fruit ? $fruit : 'apple');
if you're using PHP 7+ then you can user null-coalescing operator ??: too.
<?php
// Fetches the value of $_GET['user'] and returns 'nobody'
// if it does not exist.
$username = $_GET['user'] ?? 'nobody';
// This is equivalent to:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
// Coalescing can be chained: this will return the first
// defined value out of $_GET['user'], $_POST['user'], and
// 'nobody'.
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
?>
For more information, you can refer to this link.
For null coalescing operator use this
link
.

PHP - Elvis Vs. Null coalesce [duplicate]

Can someone explain the differences between ternary operator shorthand (?:) and null coalescing operator (??) in PHP?
When do they behave differently and when in the same way (if that even happens)?
$a ?: $b
VS.
$a ?? $b
When your first argument is null, they're basically the same except that the null coalescing won't output an E_NOTICE when you have an undefined variable. The PHP 7.0 migration docs has this to say:
The null coalescing operator (??) has been added as syntactic sugar
for the common case of needing to use a ternary in conjunction with
isset(). It returns its first operand if it exists and is not NULL;
otherwise it returns its second operand.
Here's some example code to demonstrate this:
<?php
$a = null;
print $a ?? 'b'; // b
print "\n";
print $a ?: 'b'; // b
print "\n";
print $c ?? 'a'; // a
print "\n";
print $c ?: 'a'; // Notice: Undefined variable: c in /in/apAIb on line 14
print "\n";
$b = array('a' => null);
print $b['a'] ?? 'd'; // d
print "\n";
print $b['a'] ?: 'd'; // d
print "\n";
print $b['c'] ?? 'e'; // e
print "\n";
print $b['c'] ?: 'e'; // Notice: Undefined index: c in /in/apAIb on line 33
print "\n";
The lines that have the notice are the ones where I'm using the shorthand ternary operator as opposed to the null coalescing operator. However, even with the notice, PHP will give the same response back.
Execute the code: https://3v4l.org/McavC
Of course, this is always assuming the first argument is null. Once it's no longer null, then you end up with differences in that the ?? operator would always return the first argument while the ?: shorthand would only if the first argument was truthy, and that relies on how PHP would type-cast things to a boolean.
So:
$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'
would then have $a be equal to false and $b equal to 'g'.
Ran the below on php interactive mode (php -a on terminal). The comment on each line shows the result.
var_export (false ?? 'value2'); // false
var_export (true ?? 'value2'); // true
var_export (null ?? 'value2'); // value2
var_export ('' ?? 'value2'); // ""
var_export (0 ?? 'value2'); // 0
var_export (false ?: 'value2'); // value2
var_export (true ?: 'value2'); // true
var_export (null ?: 'value2'); // value2
var_export ('' ?: 'value2'); // value2
var_export (0 ?: 'value2'); // value2
The Null Coalescing Operator ??
?? is like a "gate" that only lets NULL through.
So, it always returns first parameter, unless first parameter happens to be NULL.
This means ?? is same as ( !isset() || is_null() )
Use of ??
shorten !isset() || is_null() check
e.g $object = $object ?? new objClassName();
Stacking Null Coalese Operator
$v = $x ?? $y ?? $z;
// This is a sequence of "SET && NOT NULL"s:
if( $x && !is_null($x) ){
return $x;
} else if( $y && !is_null($y) ){
return $y;
} else {
return $z;
}
The Ternary Operator ?:
?: is like a gate that lets anything falsy through - including NULL
Anything falsy: 0, empty string, NULL, false, !isset(), empty()
Same like old ternary operator: X ? Y : Z
Note: ?: will throw PHP NOTICE on undefined (unset or !isset()) variables
Use of ?:
checking empty(), !isset(), is_null() etc
shorten ternary operation like !empty($x) ? $x : $y to $x ?: $y
shorten if(!$x) { echo $x; } else { echo $y; } to echo $x ?: $y
Stacking Ternary Operator
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 1 ?: 0 ?: 3 ?: 2; //1
echo 2 ?: 1 ?: 0 ?: 3; //2
echo 3 ?: 2 ?: 1 ?: 0; //3
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 0 ?: 0 ?: 2 ?: 3; //2
echo 0 ?: 0 ?: 0 ?: 3; //3
// Source & Credit: http://php.net/manual/en/language.operators.comparison.php#95997
// This is basically a sequence of:
if( truthy ) {}
else if(truthy ) {}
else if(truthy ) {}
..
else {}
Stacking both, we can shorten this:
if( isset($_GET['name']) && !is_null($_GET['name'])) {
$name = $_GET['name'];
} else if( !empty($user_name) ) {
$name = $user_name;
} else {
$name = 'anonymous';
}
To this:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
Cool, right? :-)
If you use the shortcut ternary operator like this, it will cause a notice if $_GET['username'] is not set:
$val = $_GET['username'] ?: 'default';
So instead you have to do something like this:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
The null coalescing operator is equivalent to the above statement, and will return 'default' if $_GET['username'] is not set or is null:
$val = $_GET['username'] ?? 'default';
Note that it does not check truthiness. It checks only if it is set and not null.
You can also do this, and the first defined (set and not null) value will be returned:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
Now that is a proper coalescing operator.
The major difference is that
Ternary Operator expression expr1 ?: expr3 returns expr1 if expr1 evaluates to
TRUE but on the other hand Null Coalescing Operator expression (expr1) ?? (expr2)
evaluates to expr1 if expr1 is not NULL
Ternary
Operator expr1 ?: expr3 emit a notice if the left-hand side
value (expr1) does not exist but on the other hand Null Coalescing Operator (expr1) ?? (expr2) In particular, does not emit a notice if the left-hand side value (expr1) does
not exist, just like isset().
TernaryOperator is left associative
((true ? 'true' : false) ? 't' : 'f');
Null Coalescing Operator is right associative
($a ?? ($b ?? $c));
Now lets explain the difference between by example :
Ternary Operator (?:)
$x='';
$value=($x)?:'default';
var_dump($value);
// The above is identical to this if/else statement
if($x){
$value=$x;
}
else{
$value='default';
}
var_dump($value);
Null Coalescing Operator (??)
$value=($x)??'default';
var_dump($value);
// The above is identical to this if/else statement
if(isset($x)){
$value=$x;
}
else{
$value='default';
}
var_dump($value);
Here is the table that explain the difference and similarity between '??' and ?:
Special Note : null coalescing operator and ternary operator is an
expression, and that it doesn't evaluate to a variable, but to the
result of an expression. This is important to know if you want to
return a variable by reference. The statement return $foo ?? $bar; and
return $var == 42 ? $a : $b; in a return-by-reference function will
therefore not work and a warning is issued.
Both of them behave differently when it comes to dynamic data handling.
If the variable is empty ( '' ) the null coalescing will treat the variable as true but the shorthand ternary operator won't. And that's something to have in mind.
$a = NULL;
$c = '';
print $a ?? '1b';
print "\n";
print $a ?: '2b';
print "\n";
print $c ?? '1d';
print "\n";
print $c ?: '2d';
print "\n";
print $e ?? '1f';
print "\n";
print $e ?: '2f';
And the output:
1b
2b
2d
1f
Notice: Undefined variable: e in /in/ZBAa1 on line 21
2f
Link: https://3v4l.org/ZBAa1
Both are shorthands for longer expressions.
?: is short for $a ? $a : $b. This expression will evaluate to $a if $a evaluates to TRUE.
?? is short for isset($a) ? $a : $b. This expression will evaluate to $a if $a is set and not null.
Their use cases overlaps when $a is undefined or null. When $a is undefined ?? will not produce an E_NOTICE, but the results are the same. When $a is null the result is the same.
For the beginners:
Null coalescing operator (??)
Everything is true except null values and undefined (variable/array index/object attributes)
ex:
$array = [];
$object = new stdClass();
var_export (false ?? 'second'); # false
var_export (true ?? 'second'); # true
var_export (null ?? 'second'); # 'second'
var_export ('' ?? 'second'); # ""
var_export ('some text' ?? 'second'); # "some text"
var_export (0 ?? 'second'); # 0
var_export ($undefinedVarible ?? 'second'); # "second"
var_export ($array['undefined_index'] ?? 'second'); # "second"
var_export ($object->undefinedAttribute ?? 'second'); # "second"
this is basically check the variable(array index, object attribute.. etc) is exist and not null. similar to isset function
Ternary operator shorthand (?:)
every false things (false,null,0,empty string) are come as false, but if it's a undefined it also come as false but Notice will throw
ex
$array = [];
$object = new stdClass();
var_export (false ?: 'second'); # "second"
var_export (true ?: 'second'); # true
var_export (null ?: 'second'); # "second"
var_export ('' ?: 'second'); # "second"
var_export ('some text' ?? 'second'); # "some text"
var_export (0 ?: 'second'); # "second"
var_export ($undefinedVarible ?: 'second'); # "second" Notice: Undefined variable: ..
var_export ($array['undefined_index'] ?: 'second'); # "second" Notice: Undefined index: ..
var_export ($object->undefinedAttribute ?: 'second'); # "Notice: Undefined index: ..
Hope this helps
Scroll down on this link and view the section, it gives you a comparative example as seen below:
<?php
/** Fetches the value of $_GET['user'] and returns 'nobody' if it does not exist. **/
$username = $_GET['user'] ?? 'nobody';
/** This is equivalent to: **/
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
/** Coalescing can be chained: this will return the first defined value out of $_GET['user'], $_POST['user'], and 'nobody'. **/
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
?>
The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.
Essentially, using the coalescing operator will make it auto check for null unlike the ternary operator.
The other answers goes deep and give great explanations. For those who look for quick answer,
$a ?: 'fallback' is $a ? $a : 'fallback'
while
$a ?? 'fallback' is $a = isset($a) ? $a : 'fallback'
The main difference would be when the left operator is either:
A falsy value that is NOT null (0, '', false, [], ...)
An undefined variable
It seems there are pros and cons to using either ?? or ?:. The pro to using ?: is that it evaluates false and null and "" the same. The con is that it reports an E_NOTICE if the preceding argument is null. With ?? the pro is that there is no E_NOTICE, but the con is that it does not evaluate false and null the same. In my experience, I have seen people begin using null and false interchangeably but then they eventually resort to modifying their code to be consistent with using either null or false, but not both. An alternative is to create a more elaborate ternary condition: (isset($something) or !$something) ? $something : $something_else.
The following is an example of the difference of using the ?? operator using both null and false:
$false = null;
$var = $false ?? "true";
echo $var . "---<br>";//returns: true---
$false = false;
$var = $false ?? "true";
echo $var . "---<br>"; //returns: ---
By elaborating on the ternary operator however, we can make a false or empty string "" behave as if it were a null without throwing an e_notice:
$false = null;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---
$false = false;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---
$false = "";
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---
$false = true;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: 1---
Personally, I think it would be really nice if a future rev of PHP included another new operator: :? that replaced the above syntax. ie:
// $var = $false :? "true"; That syntax would evaluate null, false, and "" equally and not throw an E_NOTICE...
class a
{
public $a = 'aaa';
}
$a = new a();
echo $a->a; // Writes 'aaa'
echo $a->b; // Notice: Undefined property: a::$b
echo $a->a ?? '$a->a does not exists'; // Writes 'aaa'
// Does not throw an error although $a->b does not exist.
echo $a->b ?? '$a->b does not exist.'; // Writes $a->b does not exist.
// Does not throw an error although $a->b and also $a->b->c does not exist.
echo $a->b->c ?? '$a->b->c does not exist.'; // Writes $a->b->c does not exist.
Practical short answer :
Try:
var_dump('' ?: 'ok');
vs
var_dump('' ?? 'ok');
The first one will return 'ok' if the tested value (or variable *) evaluates to false
whereas
The second one will return 'ok' if the tested value (or variable *) is null or not initialized/set.
*CAUTION : if you want to test a variable with ?:, you must first ensure it is initialized/set, otherwise PHP will raise an E_NOTICE (whereas ?? wont).
Null Coalescing operator performs just two tasks: it checks whether the variable is set and whether it is null. Have a look at the following example:
<?php
# case 1:
$greeting = 'Hola';
echo $greeting ?? 'Hi There'; # outputs: 'Hola'
# case 2:
$greeting = null;
echo $greeting ?? 'Hi There'; # outputs: 'Hi There'
# case 3:
unset($greeting);
echo $greeting ?? 'Hi There'; # outputs: 'Hi There'
The above code example states that Null Coalescing operator treats a non-existing variable and a variable which is set to NULL in the same way.
Null Coalescing operator is an improvement over the ternary operator. Have a look at the following code snippet comparing the two:
<?php /* example: checking for the $_POST field that goes by the name of 'fullname'*/
# in ternary operator
echo "Welcome ", (isset($_POST['fullname']) && !is_null($_POST['fullname']) ? $_POST['fullname'] : 'Mr. Whosoever.'); # outputs: Welcome Mr. Whosoever.
# in null coalecing operator
echo "Welcome ", ($_POST['fullname'] ?? 'Mr. Whosoever.'); # outputs: Welcome Mr. Whosoever.
So, the difference between the two is that Null Coalescing operator operator is designed to handle undefined variables better than the ternary operator. Whereas, the ternary operator is a shorthand for if-else.
Null Coalescing operator is not meant to replace ternary operator, but in some use cases like in the above example, it allows you to write clean code with less hassle.
Credits: http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples
When using the superglobals like $_GET or $_REQUEST you should be aware that they could be an empty string.
In this specal case this example
$username = $_GET['user'] ?? 'nobody';
will fail because the value of $username now is an empty string.
So when using $_GET or even $_REQUEST you should use the ternary operator instead like this:
$username = (!empty($_GET['user'])?$_GET['user']:'nobody';
Now the value of $username is 'nobody' as expected.
:? - means that if the first operand is true, it will return it. Otherwise, it will return the second one.
?? - evaluates if the first operand exists and is not null. If so, it returns it; otherwise, it returns its second operand.
I found an article that describes very nice the difference:
https://www.fparedes.com/blog/null-coalescing-vs-elvis-operator-php/

How to avoid undefined index warning for chains of 'default' values?

Let's say I want to check for a couple of different parameters, and then fall back to a default value, is there a way to do it without ugly and verbose writing of isset()?
For example in JS we can do:
var someVariable = otherVar || anotherVar || 'fallback here';
The equivalent in PHP would be something like:
$someVariable = (isset($otherVar) ? $otherVar : (isset($anotherVar) ? $anotherVar : 'fallback here'));
which is obviously a mess and horrible to read.
Lots of solutions exist for single fallbacks, i.e.:
$someVariable = $otherVar ?: 'fallback here';
but that doesn't help me with requiring more than one in the line of checks.
Given that I am only interested in whether or not the value is set or truth-y (i.e. I am happy for 1 to be accepted as the used value, and for 0/false/null to be skipped and for the next parameter in the chain to be used), what is the best way to avoid the undefined index warning?
In reality, I would be doing this on arrays in most cases, but not all, and it's probably that they will be different arrays. I may want to use $_POST for the first, then check $_GET under a different key, and then fall back to a default string for example.
Ignoring PHP warnings and notices is not a good idea at all.
But just for the experiment, I can suggest you the error control operator #.
PHP supports one error control operator: the at sign (#). When prepended to an expression in PHP, any error messages that might be generated by that expression will be ignored.
$someVariable = #$otherVar ? #$var : 'fallback here';
echo $someVariable;
// output: fallback here
http://php.net/manual/en/language.operators.errorcontrol.php
You can chain ?: but you'll still need to suppress errors with #.
For example, the following will work similarly to your JavaScript example:
$foo = #$bar ?: #$baz ?: #$qux ?: "I give up";
It's the equivalent of multiple "single fallbacks":
$foo = (#$bar ?: (#$baz ?: (#$qux ?: "I give up")));
Be careful though, ?: only checks for truthyness. There are scenarios where isset() and truthyness do not agree. Additionally, ?: fallback functionality was introduced in PHP 5.3.
If you only care about nullness and have PHP 7 available, it introduced a null coalescing operator.
This is ambiguous and it is deprecated...
$something = $a ? $b : $c ?: $d;
So, you have 2 alternatives for grouping:
$something = $a ? $b : ($c ?: $d); // version 1
$something = ($a ? $b : $c) ?: $d; // version 2
Which one is correct? Let's test this...
$posibilities = [TRUE, FALSE, NULL, [], new stdClass()];
$v1_is_correct = TRUE;
$v2_is_correct = TRUE;
foreach ($posibilities as $a) {
foreach ($posibilities as $b) {
foreach ($posibilities as $c) {
foreach ($posibilities as $d) {
$original = (int)($a ? $b : $c ?: $d);
$v1 = (int)($a ? $b : ($c ?: $d));
$v2 = (int)(($a ? $b : $c) ?: $d);
$v1_is_correct = $v1_is_correct && ($original === $v1);
$v2_is_correct = $v2_is_correct && ($original === $v2);
print "ORIG: $original - V1: $v1 - V2: $v2 \n";
}
}
}
}
print "\n";
$v1_is_correct ? print "V1 is correct \n" : NULL;
$v2_is_correct ? print "V2 is correct \n" : NULL;
Result: V2 is correct.
$a ? $b : $c ?: $d
is equivalent to...
($a ? $b : $c) ?: $d

PHP or shorthand for empty variable

$a = '';
$b = 1;
How to print $b if $a = '' using shorthand in PHP?
in javascript there is something like
a || b;
Ternary Operator
$a = '';
$b = 1;
echo $a ?: $b; // 1
Until $a is evaluated false, $b will be displayed. Remember that the following things are considered to be empty:
"" (an empty string)
0 (0 as an integer)
0.0 (0 as a float)
"0" (0 as a string)
NULL
FALSE
array() (an empty array)
$var; (a variable declared, but without a value)
That means that if $a is "", 0, "0", null, false, array(), .. then $b will be displayed. See PHP type comparison tables.
If you want to display $b only when $a is an empty string, then you should uses strict comparison operators (===)
$a = '';
$b = 1;
echo $a === '' ? $b : ''; // 1
This is the shorthand for an IF/Else statement in PHP.
echo ($a != '' ? $a : $b)
If $a is not an empty string output (echo) $a otherwise output $b.
As others ahve said Turnary operator is handy for most senarios.
echo $a ?: $b;//b
But it is NOT shorthand for empty().
Ternary operator will issue notices if var/array keys/properties are not set.
echo $someArray['key that doesnt exist'] ?: $b;//Notice: Undefined index
echo $arrayThatDoesntExist['key-that-doesnt-exist'] ?: $b;//Notice: Undefined variable
empty() will take care of the additional checks for you and its recomended to just use it.
if (empty($arrayThatDoesntExist['key-that-doesnt-exist'])) echo $b;
You could technically just suppress the warning/notice with # and the ternary operator becomes a replacement for empty().
#echo $someArray['key that doesnt exist'] ?: $b;
#echo $arrayThatDoesntExist['key-that-doesnt-exist'] ?: $b;
But usually not recommended as supressing notices and warnings could lead you into trouble later on plus I think it may have some performance impact.

Categories