In PHP I find myself writing code like this frequently:
$a = isset($the->very->long->variable[$index])
? $the->very->long->variable[$index]
: null;
Is there a simpler way to do this? Preferably one that doesn't require me to write $the->very->long->variable[$index] twice.
An update, because PHP 7 is now out and is a game-changer on this point ; the previous answers are about PHP 5.
PHP 7 solves this issue. Because you are true at saying that it is frequent to write this in PHP, and that's absolutely not elegant.
In PHP 7 comes the Null Coalesce Operator (RFC), which is a perfect shorthand for the isset ternary condition.
Its goal is to replace this type of condition:
$var = isset($dict['optional']) ? $dict['optional'] : 'fallback';
By that:
$var = $dict['optional'] ?? 'fallback';
Even better, the null coalesce operators are chainable:
$x = null;
# $y = null; (undefined)
$z = 'fallback';
# PHP 7
echo $x ?? $y ?? $z #=> "fallback"
# PHP 5
echo isset($x) ? $x : (isset($y) ? $y : $z)
The null coalesce operator acts exactly like isset() : the subject variable's value is taken if:
The variable is defined (it exists)
The variable is not null
Just a note for PHP beginners: if you use the ternary condition but you know that the subject variable is necessarily defined (but you want a fallback for falsy values), there's the Elvis operator:
$var = $dict['optional'] ?: 'fallback';
With the Elvis operator, if $dict['optional'] is an invalid offset or $dict is undefined, you'll get a E_NOTICE warning (PHP 5 & 7). That's why, in PHP 5, people are using the hideous isset a ? a : b form when they're not sure about the input.
Sadly no, because the RFC has been declined. And because isset is not a function but a language construct you cannot write your own function for this case.
Note: Because this is a language construct and not a function, it cannot be called using variable functions.
If you only assign null instead of the non set variable, you can use:
$a = #$the->very->long->variable[$index];
# makes that instruction throw no errors
Assuming you know that $the->very->long->variable is set, and you're just worried about the array index....
$x = $the->very->long->variable;
$a = isset($x[$index]) ? $x[$index] : null;
Or for a more generic variant that you can use around you code:
function array_valifset($arr,$k, $default=null) {
return isset($arr[$k]) ? $arr[$k] : $default;
}
then call it like this for any array value:
$a = array_valifset($the->very->long->variable,$index);
I stumbled across the same problem and discovered that referencing an array element does not issue a notice or warning but returns null (at least PHP 5.6).
$foo = ['bar' => 1];
var_dump($bar = &$foo['bar']); // int 1
var_dump($baz = &$foo['baz']); // null
Inside an if statement:
if($bar = &$foo['bar']) {
echo $bar;
}
if($baz = &$foo['baz']) {
echo $baz;
}
Related
Is there in PHP something similar to JavaScript's:
alert(test || 'Hello');
So, when test is undefined or null we'll see Hello, otherwise - we'll see the value of test.
I tried similar syntax in PHP but it doesn't seem to be working right... Also I've got no idea how to google this problem..
thanks
Edit
I should probably add that I wanted to use it inside an array:
$arr = array($one || 'one?', $two || 'two?'); //This is wrong
But indeed, I can use the inline '? :' if statement here as well, thanks.
$arr = array(is_null($one) ? "one?" : $one, is_null($two) ? "two ?" : $two); //OK
you can do echo $test ?: 'hello';
This will echo $test if it is true and 'hello' otherwise.
Note it will throw a notice or strict error if $test is not set but...
This shouldn't be a problem since most servers are set to ignore these errors. Most frameworks have code that triggers these errors.
Edit: This is a classic Ternary Operator, but with the middle part left out. Available since PHP 5.3.
echo $test ? $test : 'hello'; // this is the same
echo $test ?: 'hello'; // as this one
This only checks for the truthiness of the first variable and not if it is undefined, in which case it triggers the E_NOTICE error. For the latter, check the PHP7 answer below (soon hopefully above).
From PHP 7 onwards you can use something called a coalesce operator which does exactly what you want without the E_NOTICE that ?: triggers.
To use it you use ?? which will check if the value on the left is set and not null.
$arr = array($one ?? 'one?', $two ?? 'two?');
See #Yamiko's answer below for a PHP7 solution https://stackoverflow.com/a/29217577/140413
echo (!$test) ? 'hello' : $test;
Or you can be a little more robust and do this
echo isset($test) ? $test : 'hello';
As per the latest version use this for the shorthand
$var = $value ?? "secondvalue";
One-liner. Super readable, works for regular variables, arrays and objects.
// standard variable string
$result = #$var_str ?: "default";
// missing array element
$result = #$var_arr["missing"] ?: "default";
// missing object member
$result = #$var_obj->missing ?: "default";
See it in action: Php Sandbox Demo
I'm very surprised this isn't suggested in the other answers:
echo isset($test) ? $test : 'hello';
From the docs isset($var) will return false if $var doesn't exist or is set to null.
The null coalesce operator from PHP 7 onwards, described by #Yamiko, is a syntax shortcut for the above.
In this case:
echo $test ?? 'hello';
If you want to create an array this way, array_map provides a more concise way to do this (depending on the number of elements in the array):
function defined_map($value, $default) {
return (!isset($value) || is_null($value)) ? $default : $value;
// or return $value ? $default : $value;
}
$values = array($one, $two);
$defaults = array('one', 'two');
$values = array_map('defined_map', $values, $defaults);
Just make sure you know which elements evaluate to false so you can apply the right test.
Since php7.4, you can use the null coalescing assignment, so that you can do
$arr = array($one ??= "one?", $two ??= "two ?");
See the docs here
There may be a better way, but this is the first thing that came to my mind:
echo (!$test) ? "Hello" : $test;
Null is false in PHP, therefore you can use ternary:
alert($test ? $test : 'Hello');
Edit:
This also holds for an empty string, since ternary uses the '===' equality rather than '=='
And empty or null string is false whether using the '===' or '==' operator. I really should test my answers first.
Well, expanding that notation you supplied means you come up with:
if (test) {
alert(test);
} else {
alert('Hello');
}
So it's just a simple if...else construct. In PHP, you can shorten simple if...else constructs as something called a 'ternary expression':
alert($test ? $test : 'Hello');
Obviously there is no equivalent to the JS alert function in PHP, but the construct is the same.
alert((test == null || test == undefined)?'hello':test);
I recently had the very same problem.This is how i solved it:
<?php if (empty($row['test'])) {
echo "Not Provided";}
else {
echo $row['test'];}?></h5></span></span>
</div>
Your value in the database is in variable $test..so if $test row is empty then echo Not Provided
Why this line of code does not work in php like as in JS:
$id = [];
$id = null || [];
if (count($id)) {
echo 'd';
}
Why $id still is null instead empty array []? Therefore count() gives an error.
In PHP, logical operators like || always return a boolean, even if given a non-boolean output.
So your statement is evaluated as "is either null or [] truthy?" Since both null and an empty array evaluate to false, the result is boolean false.
There are however two operators which would do something similar to JS's ||:
$a ?: $b is short-hand for $a ? $a : $b; in other words, it evaluates to $a if it's "truthy", or $b if not (this is documented along with the ternary operator for which it is a short-hand)
$a ?? $b is similar, but checks for null rather than "truthiness"; it's equivalent to isset($a) ? $a : $b (this is called the null-coalescing operator)
<?php
// PHP < 7
$id = isset($id) ? $id : [];
// PHP >= 7
$id = $id ?? [];
As of PHP 7 and above
Null Coalesce Operator
Another helpful link
Watch out!
I find PHP's handling of empty to be highly questionable:
empty($unsetVar) == true (fabulous, no need to check isset as warning is suppressed!)
empty(null) == true
empty('') == true
All fine, until we get to this nonsense:
empty(false) == true. Wait, WHAT???
You've GOT to be kidding me. In no world should false be taken to mean the same thing as no value at all! There's nothing "empty" about a false assertion. And due to this logical fallacy, you cannot use empty to check ANY variable that might have a VALUE of false.
In my projects, I use a static method:
public static function hasValue($value) {
return isset($value) && !is_null($value) && $value !== '';
}
Of course, using this method, I no longer get the free warning suppression provided by empty, so now I'm also forced to remember to call the method above with the notice/warning suppression operator #:
if(self::hasValue(#$possiblyUnsetVar)) {}
Very frustrating.
This question already has answers here:
PHP short-ternary ("Elvis") operator vs null coalescing operator
(15 answers)
Closed 4 years ago.
The community reviewed whether to reopen this question 4 months ago and left it closed:
Original close reason(s) were not resolved
I was diving into Symfony framework (version 4) code and found this piece of code:
$env = $_SERVER['APP_ENV'] ?? 'dev';
I'm not sure what this actually does but I imagine that it expands to something like:
$env = $_SERVER['APP_ENV'] != null ? $_SERVER['APP_ENV'] : 'dev';
Or maybe:
$env = isset($_SERVER['APP_ENV']) ? $_SERVER['APP_ENV'] : 'dev';
Does someone have any precision about the subject?
It's the "null coalescing operator", added in php 7.0. The definition of how it works is:
It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.
So it's actually just isset() in a handy operator.
Those two are equivalent1:
$foo = $bar ?? 'something';
$foo = isset($bar) ? $bar : 'something';
Documentation: http://php.net/manual/en/language.operators.comparison.php#language.operators.comparison.coalesce
In the list of new PHP7 features: http://php.net/manual/en/migration70.new-features.php#migration70.new-features.null-coalesce-op
And original RFC https://wiki.php.net/rfc/isset_ternary
EDIT: As this answer gets a lot of views, little clarification:
1There is a difference: In case of ??, the first expression is evaluated only once, as opposed to ? :, where the expression is first evaluated in the condition section, then the second time in the "answer" section.
$myVar = $someVar ?? 42;
Is equivalent to :
$myVar = isset($someVar) ? $someVar : 42;
For constants, the behaviour is the same when using a constant that already exists :
define("FOO", "bar");
define("BAR", null);
$MyVar = FOO ?? "42";
$MyVar2 = BAR ?? "42";
echo $MyVar . PHP_EOL; // bar
echo $MyVar2 . PHP_EOL; // 42
However, for constants that don't exist, this is different :
$MyVar3 = IDONTEXIST ?? "42"; // Raises a warning
echo $MyVar3 . PHP_EOL; // IDONTEXIST
Warning: Use of undefined constant IDONTEXIST - assumed 'IDONTEXIST' (this will throw an Error in a future version of PHP)
Php will convert the non-existing constant to a string.
You can use constant("ConstantName") that returns the value of the constant or null if the constant doesn't exist, but it will still raise a warning. You can prepended the function with the error control operator # to ignore the warning message :
$myVar = #constant("IDONTEXIST") ?? "42"; // No warning displayed anymore
echo $myVar . PHP_EOL; // 42
$x = $y ?? 'dev'
is short hand for x = y if y is set, otherwise x = 'dev'
There is also
$x = $y =="SOMETHING" ? 10 : 20
meaning if y equals 'SOMETHING' then x = 10, otherwise x = 20
I know you can assign a variable in a condition like this:
if ($var = $foo)
However I don't need to do anything in the condition itself, so I'm often left with empty brackets. Can I simply assign $var if $foo is true in some other way without needing to do something else later?
Also can I assign $var to $foo if $foo is true but if $foo is false do something else? Like:
if ($var = !$foo) {
if ($var = !$bar) {
//Etc...
}
}
Basically I want to have more fallbacks/defaults.
#chandresh_cool's suggestion is right but to allow multiple possiblities / fallbacks you would have to nest the ternary expressions:
$var = ($foo == true) ? $foo:
($bar == true) ? $bar:
($fuzz == true) ? $fuzz:
$default;
Note: the first 3 lines end in colons not semi-colons.
However a simpler solution is to do the following:
$var = ($foo||$bar||$fuzz...);
Although this is a very old post. Fallback logic on falsify values can be coded like this.
$var = $foo ?: $bar ?: "default";
In this case when $foo is a falsified value (like false, empty string, etc.) it will fall back to $bar otherwise it uses $foo.
If bar is a falsified value, it will fallback to the string default.
Keep in mind, that this works with falsified values, and not only true.
example:
$foo = "";
$bar = null;
$var = $foo ?: $bar ?: "default";
$var will contain the text default because empty strings and null are considered "false" values.
[update]
In php 7 you can use the new null coalescing operator: ??, which also checks if the variable exists with isset(). This is usefull for when you are using a key in an array.
Example:
$array = [];
$bar = null;
$var = $array['foo'] ?? $bar ?? "default";
Before php 7 this would have given an Undefined index: foo notice. But with the null coalescing operator, that notice won't come up.
Instead you can Use ternary operator like this
$var = ($foo == true)?$foo:"put here what you want";
You can assign values like this:
$var = $foo;
Setting them within an if statement is also possible, PHP will evaluate the resulting $var which you just assigned.
I dont really get your question, but you could do something like this:
if(!($var = $foo)){
//something else.
}
In Ruby you can easily set a default value for a variable
x ||= "default"
The above statement will set the value of x to "default" if x is nil or false
Is there a similar shortcut in PHP or do I have to use the longer form:
$x = (isset($x))? $x : "default";
Are there any easier ways to handle this in PHP?
As of PHP 5.3 you can use the ternary operator while omitting the middle argument:
$x = $x ?: 'default';
As of PHP 7.0, you can also use the null coalesce operator
// PHP version < 7.0, using a standard ternary
$x = (isset($_GET['y'])) ? $_GET['y'] : 'not set';
// PHP version >= 7.0
$x = $_GET['y'] ?? 'not set';
isset($x) or $x = 'default';
As of PHP 7.4 you can write:
$x ??= "default";
This works as long as $x is null. Other "falsy" values don't count as "not set".
I wrap it in a function:
function default($value, $default) {
return $value ? $value : $default;
}
// then use it like:
$x=default($x, 'default');
Some people may not like it, but it keeps your code cleaner if you're doing a crazy function call.
I think your longer form is already the shortcut for php... and I wouldn't use it, because it is not good to read
Some notice:
In the symfony framework most of the "get"-Methods have a second parameter to define a default value...