Check method in method exists or is not null [duplicate] - php

This question already has answers here:
Is there a "nullsafe operator" in PHP?
(3 answers)
Closed 1 year ago.
Is there a better way to check all this in less lines of code?
if (
$item->getProduct() !== null
&& $item->getProduct()->getMedia() !== null
&& $item->getProduct()->getMedia()->count()
&& $item->getProduct()->getMedia()->first() !== null
&& $item->getProduct()->getMedia()->first()->getMedia()
) {
$imageUrl = $item->getProduct()->getMedia()->first()->getMedia()->getUrl();

In PHP 8.0, there is a new "nullsafe operator", spelled ?-> for exactly this purpose: it calls the method only if the value is not null.
The only part if can't do is the extra check on ->count(), but as long as ->first() returns null rather than an error on an empty set, this would work:
$imageUrl = $item?->getProduct()?->getMedia()?->first()?->getMedia()?->getUrl();
Unless and until you can upgrade to PHP 8, your best bet will be to look for ways to improve the API to avoid this problem in the first place. In line with the Law of Demeter, you could define additional methods so that you could write this:
$imageUrl = $item->hasProductMedia() ? $item->getProductMedia()->first()->getUrl() : null;
The implementation of hasProductMedia() and getProductMedia() still need those checks, but they're hidden away rather than written each time you need to access it.
Another approach is the "Null Object Pattern" (hat tip to Markus Zeller for mentioning this in comments). Instead of returning null, each method returns a special "empty object" satisfying the correct interface.
So $item->getProduct() would never return null, but might return a NullProduct; calling getMedia() on that, or any product without any media, would return an EmptyMediaList; and so on. Eventually, you'd call getUrl() on a NullMediaItem, and it would give you a null value.

Related

Checking if variable exist and if it has a certain value in one line [duplicate]

This question already has answers here:
Does PHP have short-circuit evaluation?
(8 answers)
Closed 9 months ago.
I have always thought that if I want to check if a variable exists and has a certain value I have to use two if conditions:
if(isset($x)){
if($x->age==5){}
}
But I realized its also possible to do it in one line this way:
if(isset($x) && ($x->age==5)){}
Can someone tell me why the second variation will not result in an error if $x is null. Given that $x is null and doesn't have the property age? Would it be trying to access a property that doesn't exist?
$x=null;
Because $x is null, isset($x) is false. Then, because of the logical operator "AND" (&&), the condition cannot be fully validated, so, the test is stopped here and ($x->age==5) is not executed.
For a shorter code, as of PHP 8.0.1, you can use the NullSafe Operator (?->)
if ($x?->age == 5) { }

What is the difference between "?" and "= null" in PHP function parameters [duplicate]

This question already has answers here:
What is the purpose of the question marks before type declaration in PHP7 (?string or ?int)?
(4 answers)
Closed 1 year ago.
I was doing some research but wasn't able to find an answer (probably beacause I did not searched it right)
Consider this piece of code:
public function foo(?array $optionalParam);
And then this one:
public function foo(array $optionalParam = null);
What differs between them? Using PHPstorm I noticed that when I use the ?, it creates a PHPdoc and mark the variable type as type|null. But when I call the function without that argument, PHP screams on my face "you kidding me? where is $optionalParam". In the other side, I managed to use with no problems the =null option.
Sorry if this question is too simple, but i did not find any answers online.
First of all, the ? goes before the type, not after... other than this:
Using
public function foo(?array $optionalParam);
you are forced to pass something, that can be either null or an array, infact:
<?php
function foo(?array $optionalParam){
echo "test";
}
foo(); // doesn't work
foo(null); // works
foo([]); // works
where instead using
public function foo(array $optionalParam = null);
will accept null, an array, or 0 parameters
<?php
function foo(array $optionalParam = null){
echo "test";
}
foo(null); // works
foo(); // work
foo([]); // works
It's a PHP 7.1 feature called Nullable Types
Both of the lines you wrote are identical.
array ?$optionalParam : either an array or null
array $optionalParam = null : either an array or null
Tho using ? you'd still need to add the parameter when calling the function.

How to safely chain methods? [duplicate]

This question already has answers here:
Is there a "nullsafe operator" in PHP?
(3 answers)
Closed 2 years ago.
Is there a way to "safely" chain methods in PHP and simply return null if some previous method returns null? Otherwise, an error would be thrown: trying to get property on non-object;
For example, the following code checks whether a customer's phone number has changed using a QuickBooks SDK. I don't have control over these methods.
$customer->getPrimaryPhone() will always return an object since the form wouldn't have been submitted otherwise, but $old->getPrimaryPhone() may return null if no phone number existed previously.
The following is required to get the phone number:
$old->getPrimaryPhone()->getFreeFormNumber()
If getPrimaryPhone() returns null, then an error would be thrown.
My question is: How would I avoid code repition in the following case?
if (!empty($old->getPrimaryPhone())) {
if ($customer->getPrimaryPhone()->getFreeFormNumber() !== $old->getPrimaryPhone()->getFreeFormNumber()) {
// Repetive code here
}
} else {
// Repetive code here
}
I'd be inclined to implement an equals method on your PhoneNumber class (or whatever it's called). For example
public function equals(PhoneNumber $otherNumber) {
return $otherNumber !== null && $this->getFreeFormNumber() === $otherNumber->getFreeFormNumber();
}
Then you can simply use
if (!$customer->getPrimaryPhone()->equals($old->getPrimaryPhone())
If you've got other logic that needs to be applied (as indicated in your comment about arrays), you can easily implement that in the equals method.

Why is if(empty(strlen(trim($_POST['name'])))) invalid? [duplicate]

This question already has answers here:
Can't use method return value in write context
(8 answers)
Closed 8 years ago.
I have a if statement check to see if a string is empty
if(empty(strlen(trim($_POST['name'])))){
$error_empty = true;
}
gives me this error:
Fatal error: Can't use function return value in write context in C:\xampp\htdocs\requestaccess\index.php on line 51
empty is not a function -- it's a "language construct" that prior to PHP 5.5 can only be used to evaluate variables, not the results of arbitrary expressions.
If you wanted to use empty in exactly this manner (which is meaningless) you would have to store the result in an intermediate variable:
$var = strlen(trim($_POST['name']));
if(empty($var)) ...
But you don't need to do anything like this: strlen will always return an integer, so empty will effectively be reduced to checking for zero. You don't need empty for that; zero converts to boolean false automatically, so a saner option is
if(!strlen(trim($_POST['name']))) ...
or the equivalent
if(trim($_POST['name']) === '') ...

Why this expression return error and how can I resolve? [duplicate]

This question already has answers here:
Weird PHP error: 'Can't use function return value in write context'
(12 answers)
Closed 9 years ago.
This code:
if(!empty(trim($_POST['post']))){ }
return this error:
Fatal error: Can't use function return value in write context in ...
How can I resolve and avoid to do 2 checks ( trim and then empty ) ?
I want to check if POST is not only a blank space.
you cant use functions inside isset , empty statements. just assign the result of trim to a variable.
$r = trim($_POST['blop']);
if(!empty($r))....
edit: Prior to PHP 5.5
if (trim($_POST['post'])) {
Is functionally equivalent to what you appear to be trying to do. There's no need to call !empty
if (trim($_POST['post']) !== "") {
// this is the same
}
In the documentation it actually explains this problem specifically, then gives you an alternate solution. You can use
trim($name) == false.
In PHP, functions isset() and empty() are ment to test variables.
That means this
if(empty("someText")) { ... }
or this
if(isset(somefunction(args))) { ... }
doesn't make any sence, since result of a function is always defined, e.t.c.
These functions serve to tell wether a variable is defined or not, so argument must me a variable, or array with index, then it checks the index (works on objects too), like
if(!empty($_POST["mydata"])) {
//do something
} else {
echo "Wrong input";
}

Categories