Null coalescing at the end of array or object accessing syntax will work perfectly well without any notices, warnings or errors so long as you are (respectively) only trying to access keys or properties (no method calls).
Code: (Demo) (the same for both with isset())
var_export($array['does']['not']['exist'] ?? 'nope');
echo "\n---\n";
var_export($obj->does->not->exist ?? 'nope');
Output:
'nope'
---
'nope'
Not even mixed access (a path containing keys and properties to a value) are problematic (the behavior remains the same when using isset()). (Demo)
var_export($obj->does[123]->not->exist[678]['foo'] ?? 'nope');
// nope
From PHP8.2, for scenarios where you want to use array_key_exists() (aka key_exists()) or property_exists(), you can use null-safe arrows and a null coalescing operator. (Demo)
var_export(
key_exists(
'foo',
$obj?->does[123]?->not?->exist[678] ?? []
)
? 'yep'
: 'nope'
);
And
var_export(
property_exists(
$obj?->does[123]?->not?->exist[678] ?? (object) [],
'foo'
)
? 'yep'
: 'nope'
);
The null-safe operator is necessary before chaining a method if the leftside nullable object is guaranteed to exist.
See Is there a "nullsafe operator" in PHP?
If you have a basic class like this:
class Test
{
public function doThing($v) {
return $v;
}
}
Then you run this code:
$object = null;
var_export($object->doThing('foo') ?? 'oops');
You will get:
Fatal error: Uncaught Error: Call to a member function doThing() on null
If you instead run this code:
$object = null;
var_export($object?->doThing('foo'));
You will see that the doThing() method will not be reached and null will be displayed.
Differently from $object being assigned a null value, if $object isn't defined at all, you get Warning: Undefined variable $object. Warning Demo Fixed Demo
var_export($object?->doThing('foo')); // Warning
var_export(($object ?? null)?->doThing('foo')); // Fixed
So ultimately, don't use the null-safe operator unless you have methods later in your chain.
Also do not confuse the "null-safe operator" as meaning "undeclared-or-null-safe operator. If you are going to chain using the nullsafe operator, you must ensure that the operator is attached to an object or a null value.
Now that we have pipe operators to chain functions to data in PHP8.5, it can be said that functions can be chained to arrays, but in this context there is no need to defend or short circuit when a null value is encountered. The chained function may have no problem consuming null values. Demo
$a = null;
$a |> var_export(...);
Answer from mickmackusa on Stack OverflowFrom PHP 8, you are able to use the null safe operator which combined with the null coalescing operator allows you to write code like:
echo $data->getMyObject()?->getName() ?? '';
By using ?-> instead of -> the chain of operators is terminated and the result will be null.
The operators that "look inside an object" are considered part of the chain.
- Array access ([])
- Property access (->)
- Nullsafe property access (?->)
- Static property access (::)
- Method call (->)
- Nullsafe method call (?->)
- Static method call (::)
e.g. for the code:
$string = $data?->getObject()->getName() . " after";
if $data is null, that code would be equivalent to:
$string = null . " after";
As the string concatenation operator is not part of the 'chain' and so isn't short-circuited.
Nullsafe operator allows you to chain the calls avoiding checking whether every part of chain is not null (methods or properties of null variables).
PHP 8.0
$city = $user?->getAddress()?->city
Before PHP 8.0
$city = null;
if($user !== null) {
$address = $user->getAddress();
if($address !== null) {
$city = $address->city;
}
}
With null coalescing operator (it doesn't work with methods):
$city = null;
if($user !== null) {
$city = $user->getAddress()->city ?? null;
}
Nullsafe operator suppresses errors:
Warning: Attempt to read property "city" on null in Fatal error:
Uncaught Error: Call to a member function getAddress() on null
However it doesn't work with array keys:
$user['admin']?->getAddress()?->city //Warning: Trying to access array offset on value of type null
$user = [];
$user['admin']?->getAddress()?->city //Warning: Undefined array key "admin"
Sorry if I missed it from previous discussions, but while playing with PHP 8.0 beta1, I've found that usage of nullsafe operator (?->) on undefined variable or array key or object property does emit PHP warning.
As null coalescing operator (??) suppress similar kind of warnings, I though ?-> would work the same. Can I know any reason behind this? Only thing I can guess that it helps us to debug that which one is null value in long chain.
$object?->invalid?->property?->nonexistent?->method();
PHP warning will report if any property of this chain does not exists. But the same can be said for ?? one. Then?
https://3v4l.org/bjdCu
Thank You.
You can use "Null coalescing operator" ??
https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.null-coalesce-op
Then you will get no "array key does not exists" message if array keys are not set
$foo['data']['main'] = 'apple';
$foo['data']['extra'] = ['banana', 'orange'];
$data = array_merge(
[$foo['data']['main']] ?? [],
$foo['data']['extra'] ?? []
);
Result:
Array ( [0] => apple [1] => banana [2] => orange )
$foo['data']['main'] = 'apple';
$data = array_merge(
[$foo['data']['main']] ?? [],
$foo['data']['extra'] ?? []
);
Result:
Array ( [0] => apple )
You can use the @ operator to suppress warnings.
$data = array_merge(
[@$foo['data']['main']] ?: [],
@$foo['data']['extra'] ?: []
);
Note that [$foo['data']['main']] ?: [] won't create an empty array by default, with or without the @ operator (which just suppresses the warning). If the main element doesn't exist, this defaults to NULL, so it's equivalent to [NULL] ?: []. Since [NULL] is not an empty array, the ternary operator returns it, not the [] default.
So what you need is an ordinary ternary operator, since the null value is at a different level in the array nesting.
$data = array_merge(
@$foo['data']['main'] ? [$foo['data']['main']] : [],
@$foo['data']['extra'] ?: []
);