A simple-looking construct is needed for the use of sometimes-declared variables. After considering alternatives, I propose adding a function-like language construct for the purpose of coalescing undeclared variables.
The common challenge: Need to test the value of a variable whose existence is unknown.
Existing solutions:
$input = $_POST['input'] ?? 'none';
if ($input === 'yes') echo 'success';
$_POST['input'] ??= 'none';
if ($_POST['input'] === 'yes') echo 'success';
Needed solution: What we don’t have is a Variable Handling Function that will concisely resolve any uninitialized variable.
// Hypothetical
if (nullc($_POST['input']) === 'yes') echo 'success';
The proposed construct nullc(mixed $var): mixed
will return the original value, or null
if the variable is not declared. This is consistent with the construct isset
which returns false
when a variable is assigned to null
. In this way, the two constructs isset
and nullc
will complement each other more concisely than something like the construct empty
.
The other challenge: Null coalescing operator precedence causes unexpected behavior.
$test = 'off';
if ($test ?? '' === 'on') {
// The line above is equivalent to if ($test ?? false) and will evaluate as true.
echo 'yes';
}
if ('on' === $what ?? '') {
// The line above is equivalent to if (('on' === $what) ?? '') and will throw a warning
}
This requires an extra set of parentheses to be workable.
$test = 'off';
if (($test ?? '') === 'on') {
// The line above will evaluate as false.
}
These nuances were missed in the former Unary Coalesce RFC. Adding or not adding an operator doesn’t resolve the cumbersome precedence already in place for ??
usage. I was reminded of the need for a function-style construct while contemplating the differences between PHP’s ??
operator and Microsoft’s function Nz
. What we can do with an expression like nullc($test) === 'on'
should be compatible with other existing operators and is more elegant than operators-in-parentheses or any multi-line statements. This would also resolve the problem of not being able to do the same in a user function.