Is there a "nullsafe operator" in PHP? - php

Is there any way to write the following statement using some kind of safe navigation operator?
echo $data->getMyObject() != null ? $data->getMyObject()->getName() : '';
So that it looks like this:
echo $data->getMyObject()?->getName();

From 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"

No there is not.
The absolute best way to deal with this is to design your objects in a way that they always return a known, good, defined value of a specific type.
For situations where this is absolutely not possible, you'll have to do:
$foo = $data->getMyObject();
if ($foo) {
echo $foo->getName();
}
or maybe
echo ($foo = $data->getMyObject()) ? $foo->getName() : null;

Related

PHP - Undefined index solving returns warining

I have a function within my PHP project which has some specific params..
$user_sequence = $user['user_sequence'];
if ($cached || !$user_sequence) {
return;
}
Notice: Undefined index: user_sequence
I have fixed that with:
if (isset($user['user_sequence'])) {
$user_sequence = $user['user_sequence'];
}
But now my second if() clause get's a warning:
Variable '$user_sequence' is probably undefined
Would setting it to null before if() be the best approach to solve it? Thanks
Spelled out in full, you need to specify what the value should be if $user['user_sequence'] is not set. In your second if statement, you are checking !$user_sequence, so a logical default value would be boolean false:
if (isset($user['user_sequence'])) {
$user_sequence = $user['user_sequence'];
}
else {
$user_sequence = false;
}
Luckily, PHP doesn't make use write out that whole if statement, because we can use the null coalescing operator, and shorten it to this:
$user_sequence = $user['user_sequence'] ?? false;
In other situations, you might want to default to an empty array ($something ?? []) or even just null ($something ?? null).

PHP - when to use error suppressing operator ( #( $obj->var ) ) and when to use null coalescing operator ( ?? )

I'm setting a variable on an object like this:
$new_var = #( $my_obj->var_value ) ?: '';
But this can be done with the null coalescing operator as well:
$new_var = $my_obj->var_value ?? '';
I'm thinking that the first option is the safest choice, since if $my_obj is null, then $my_obj->var_value would throw a runtime error, trying to access var_value on a null object. Or what?
But then my question is, when is it the better choice to ever use ?? over the single-line ternary shorthand #( $foo->bar ) ?: ''?
The # operator is sometimes called the "shut up" operator: it silences any and all warnings and errors produced by the given statement. That makes it a rather crude tool: rather than saying "I am aware of a specific case in this code which I need to handle", it says "whatever goes wrong, just carry on and don't tell me about it".
In contrast, the ?? operator (and the newer ?-> operator) handle one specific case: the left-hand side might be null or unset, and you want to define the behaviour if it is.
The effect of the two expressions is probably quite similar in this case, but the intent with the ?? operator is much clearer.
Even better is to write code where you don't need such cases at all - for instance, a private property that is only written in the constructor is always in a known state; a public method returning that value can then return it without extra error suppression.
So instead of:
class MyClass {
public $var_value;
}
$my_obj = new MyClass;
// I might have forgotten to set the property, so coalesce it
echo $my_obj->var_value ?? '';
You can write:
class MyClass {
private string $var_value;
public function __construct(string $var_value) {
$this->var_value = $var_value;
}
public function get_var_value() {
return $this->var_value;
}
}
$my_obj = new MyClass('hello');
// No way for this to error, so no extra handling needed
echo $my_obj->get_var_value();

Difference Between null coalescing operator (??) and nullsafe operator (?->) introduced in PHP 8

I can use ?? operator in PHP to handle an index of array which is not defined.
I am confused if null safe operator offers me same or extends ?? operator's functionality?
Edit:
I can do in existing PHP versions to check if there is a specific property is defined in the array:
$user_actions = ['work' => 'SEO','play' => 'Chess', 'drink' => 'coffee'];
$fourth_tag = $user_tags['eat'] ?? "n/a";
I am trying to understand whether null safe operator is offering me something better to do so?
Null coalescing operator (??) work as an if statement it takes two values if first is null then it is replaced by second.
$a = null;
$b = $a ?? 'B';
Here $b will get the value B as $a is null;
In PHP8, NullSafe Operator (?->) was introduced will gives option of chaining the call from one function to other. As per documentation here: (https://www.php.net/releases/8.0/en.php#nullsafe-operator)
Instead of null check conditions, you can now use a chain of calls with the new nullsafe operator. When the evaluation of one element in the chain fails, the execution of the entire chain aborts and the entire chain evaluates to null.
Here is the example from documentation:
$country = null;
if ($session !== null) {
$user = $session->user;
if ($user !== null) {
$address = $user->getAddress();
if ($address !== null) {
$country = $address->country;
}
}
}
But in PHP8 you can simply do this:
$country = $session?->user?->getAddress()?->country;
So the working of both operators is significantly different.

PHP Null coalescing operator usage [duplicate]

This question already has answers here:
Is there a "nullsafe operator" in PHP?
(3 answers)
Closed 3 months ago.
Having this example code using the tertiary operator in PHP, I get the 'default value'.
$myObject = null; // I'm doing this for the example
$result = $myObject ? $myObject->path() : 'default value';
However, when I try to use the null coalescing operator to do this, I get the error
Call to a member function path() on null
$result = $myObject->path() ?? 'default value';
What am I doing wrong with the ?? operator?
?? will work if the left hand side is null or not set, however in your case the left hand cannot be evaluated if $myObject is null.
What you should consider in your case is the new nullsafe operator available with PHP 8 (so need to wait on that)
$result = $myObject?->path() ?? 'default value';
This should make the left hand side null if $myObject is null
Until then you can just do:
$result = ($myObject ? $myObject->path() : null) ?? 'default value';
This differs from your first use case in that you get default value if either $myObject or $myObject->path() are null
These snippets do not work in the same way:
$result = $myObject ? $myObject->path() : 'default value'; says: use 'default value' if $myObject is NULL
$result = $myObject->path() ?? 'default value'; says: use the default if $myObject->path() returns NULL - but that call can only return something if the object itself is not NULL

getopt -> return PHP Notice: Undefined index:

I'm using getopt to pass variables to my script, but I get the message:
PHP Notice: Undefined index:
Here's my code:
$MyOptions = getopt("c:hp:");
if ($MyOptions['c']) { //line wher error show up!
$MyClub = $MyOptions['c'];
} else {
$MyClub = '53';
}
What did I miss?
The problem is the index c in your $MyOptions array does not exist, you can avoid this in a number of ways, but my preferred option in this case would be to replace the entire if-else statement with;
$MyClub = $MyOptions['c'] ?? '53';
The ?? is the Null Coalescing operator.
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.
Please be aware this is only available from PHP 7, otherwise you will have to use an isset() to check if the index exists.

Categories