PHP Shorthand ifelse understanding - php

I am trying to make some sense out of the following shorthand
$state = $account->getCity() ? $account->getCity()->getStates() : null;
Is my understanding right?
if $account->getCity() exist assign the value of $account->getCity()->getStates() to the $state variable else assign is null
Reason I am asking this is because I m getting the error
Error: Call to a member function getCity() on a non-object
If the code $state = $account->getCity() ? $account->getCity()->getStates() : null; does not check to see if $account->getCity() is null then how do I make it so it checks it.
The output I am trying to achieve is
if $account->getCity() is not null assign the value of $account->getCity()->getStates() to the $state else just make it null
Hopefully I am not sounding too confusing :)

You're currently using what is known as "ternary operator" shorthand. However, you're using the $account->getCity() method to try and check if $account->getCity() exists, resulting in the problem.
A better practice would be to use isset($account->getCity()) or (!empty($account->getCity())) to evaluate if it exists. It is worth noting that isset() will check if it exists, where as empty() will check if it exists AND is filled with a value. As comments mention, you may also need to check that the object is actually an object, which can be done with is_object($object), such as using (is_object($account) && !empty($account->getCity()).
A common issue seen is that a variable or object may be assigned, but the contents are empty, similar to using $variable = '';. Checking using empty() may save you the heartache of coming across this problem down the road.
An additional side note is that while ternary operators are fantastic, they are best used when both a true and false condition are supplied. If you insist, try to at least use null in place of '' in the operation.

Related

Replacing array_key_exists() with isset() in PHP

Knowing the differences of array_key_exists() and isset() in PHP, I see a lot of advocates on the web suggesting for replacing array_key_exists() with isset(), but I am thinking is it safe to do so?
In one project, I have the value of $var submitted by users. The value can be anything, even NULL or not set at all. I want to use !empty($var) to check if $var holds a non-empty value, but I understand that using !empty($var) alone is dangerous since if $var isn't pre-defined, PHP will throw an error.
So I have isset($var) && !empty($var) for checking whether $var holds a non-empty value.
However, things get complicated when I have a value stored in an assoc array. Compare the followings, assuming array $arr always exists but the key foo may or may not exist in $arr.
// code snipplet 1
$arr = array();
echo isset($arr['foo']);
// code snipplet 2
$arr = array();
echo array_key_exists('foo', $arr) && !is_null($arr['foo']);
Code snipplet 2 will always work but it seems clumsy and harder to read. As for code snipplet 1, I had bad experience... I wrote something like that before in the past on a development machine. It ran fine, but when I deployed the code to the production machine, it threw errors simply because key didn't exist in array. After some debugging, I found that the PHP configs were different between the development and the production machines and their PHP versions are slightly different.
So, I am thinking is it really that safe to just replace array_key_exists() with isset()? If not, what can be of better alternatives of code snipplet 2?
In one project, I have the value of $var submitted by users.
How does that work? Users shouldn't be able to set variables. They should be able to, e.g., submit form values which end up in $_POST. I repeat, they should not be able to directly create variables in your scope.
If "users" here means some sort of plugin system where people write and include PHP code… then you may want to think about defining a more stable interface than setting variables.
The value can be anything, even NULL…
Not if it's a value submitted through HTTP. HTTP has no concept of null. It's either an empty string or doesn't exist at all.
using !empty($var) alone is dangerous since if $var isn't pre-defined, PHP will throw an error
That is wrong. empty specifically exists to test a variable against false without throwing an error. empty($var) is the same as !$var without triggering an error if the variable doesn't exist.
So I have isset($var) && !empty($var) for checking whether $var holds a non-empty value.
See Why check both isset() and !empty(). (Spoiler: it's redundant.)
echo isset($arr['foo']);
echo array_key_exists('foo', $arr) && !is_null($arr['foo']);
These both do exactly the same thing. isset returns true if the value exists and its value is not null. The second line returns true if the array key exists and its value is not null. Same thing.
I had bad experience...
You'd need to be more detailed about that, since there should be no caveat to isset as you describe it.
See The Definitive Guide To PHP's isset And empty and Difference between isset and array_key_exists.

Alternative to isset(user_input) in php

I was wondering whether is another way to check if a variable coming from user input is set and not null, besides (the obvious choice) isset().
In some cases, we may not be using $_POST to get the value, but some similar custom function. isset() can not be used on the result of a function call, so an alternative way to perform the same check must be made. Now, isset() verifies two things:
Whether the value was set.
Whether the value is null. But there is some difference between assigning a variable the null value ( $variable = NULL; ) and getting a null value due to empty input fields. Or at least so I read.
So, is there a good way of checking both these requirements without using isset() ?
The equivalent of isset($var) for a function return value is func() === null.
isset basically does a !== null comparison, without throwing an error if the tested variable does not exist. This is a non-issue for function return values, since a) functions must exist (or PHP will exit with a fatal error) and b) a function always returns something, at least null. So all you really need to do is to check for null, no isset necessary.
I've written about this extensively here: The Definitive Guide To PHP's isset And empty.
Beyond this, it depends on what exactly you want to check:
test if a key was submitted via GET/POST: isset($_POST['key'])
test if there's a value and whether it's not == false: !empty($_POST['key'])
test if it's a non-empty string: isset($_POST['key']) && strlen($_POST['key'])
perhaps much more complex validations: filter_input
Here are some options...
PHP 7.4+ : null coalescing assignment operator
$variable ??= '';
PHP 7.0+ : null coalescing operator
$variable = $var ?? '';
PHP 5.3+ : ternary operator
isset($variable) ?: $var = '';
You can also use !empty() in place of isset()
the function !empty() works for both isset() and check whether the value of any string is not null, 0 or any empty string.
I usually prefer !empty() whenever I need to compare variable existence or in terms of its value.
The best way is isset but if you insist ... try empty() and strlen() Function to check wether it is empty or string lenghth is bigger than so many characters.
strlen() returns a number, length of the variable passed to it.
empty() checks if it has character in it or if it is null. with empty() you have to be becareful because some functions return 0 or false which is not considered empty.
if(!empty($var))....
OR
if(strlen($var)>2)...
I do it in most cases like this:
$v = my_func();
if (isset($v) and $v) {
...
}

isset() and NOT operator

I know about questions like this one. There are lots of them with great answers.
I know this was "fixed" in PHP 5.5.x, but I'm unfortunately I'm using 5.3.x.
$iHatePHP = $node->get($key);
if (isset($node->get($key)) ...
The error I get:
Fatal error: Can't use method return value in write context in ...
I know the "fix" is to put the result of get() into a variable and call isset() on that. However, in order to save writing that thousands of times in my code, is it equivalent or am I missing some cases?
$iHatePHP = $node->get($key);
if (!($node->get($key)) ...
Edit: I control get(). So I can make it return anything I like, such as NULL, FALSE or ""
The isset() pseudo-function checks not for a variable that would cast to false, but for one which is null. Additionally, it checks for a variable or array key's existence; a non-existent variable would be null anyway, but would also issue a Notice, in case you had mistyped the name or similar.
When you are testing the result of a function or method call, you know that there is some return value (a function with no return statement, or a plain return; with no value, is returning null), so the extra case of "no such variable" is impossible. The easiest way to test the value is therefore is_null:
if ( is_null($node->get($key)) ) ...
If $node->get($key) returns false, 0, or '', the ! version would enter the if statement due to the rules on converting other types to boolean.
The similar empty() construct does evaluate as though you had applied a ! operator, but preserves the special behaviour for non-existent variables - empty($foo) is effectively the same as ! isset($foo) || ! (bool)$foo.

isset or !empty for $_GET[var]

i recently had to do a "test" for a job, and i got feed back saying that this statement was incorrect:
$images = $flickr->get_images(5, !empty($_GET['pg']) ? $_GET['pg'] : 1);
The "supposed" error was generated via the ternary operator on the first time the page was loaded, as there was no "?pg=1" (or whatever) passed via the query string.
The feed back said i should have used isset instead. I have looked at various posts both here (question 1960509) and blogs, but cannot find any definitive answer.
Is this really an error? How can i replicate this issue? do i need to put on E_STRICT or something in my php.ini file? Or might this be due to an older version of php?
Note: please don't tell me about how i should validate things.. i know this... it was a test to just see if i could use the flickr api calls.
This is perfectly fine. empty is not an actual function, it's a language construct. It does not issue a warning if a variable is not set (in that case the variable is considered empty, thus the 'function' returns TRUE just as you want), and additionally it checks for empty or zero values.
You could see empty as a normal isset check with an additional loose comparison to FALSE:
empty($var) === (!isset($var) || $var == FALSE)
$images = $flickr->get_images(5, (isset($_GET['pg']&&($_GET['pg']))) ? $_GET['pg'] : 1);
without isset you'll get error so combine them
I'd use
$images = $flickr->get_images(5, array_key_exists('pg', $_GET) ? $_GET['pg'] : 1);
Combine with !empty($_GET['pg']) if needed (i.e. array_key_exists('pg', $_GET) && !empty($_GET['pg'])), but array_key_exists is the intended function for this job.
I think in a situation like this isset is the correct function to use as it is checking the existence of the array element rather than checking if the value of the element has been set. As Martin notes, the best thing to do here is combine them as this will only check the value if the element exists, meaning that the error will not occur on the first page load.
Also, I think this will only give a warning if E_NOTICE is on (or perhaps E_WARNING as well)
The reason you would get an error is because the empty function is designed to check the value of an existing variable, whearas isset() is designed to tell you whether a variable has been instantiated, however because empty() is a language construct technically it doesn't throw an error or create a warning so most people don't see the difference.
From the docs:
empty() is the opposite of (boolean) var, except that no warning is generated when the variable is not set.
isset — Determine if a variable is set and is not NULL. So "isset" is the correct function to use for checking for value is set or not.
More details :http://php.net/manual/en/function.isset.php

Which is better for checking values: isset or = NULL?

I have a URL that would be like so:
http://mysite.com/index.php?somename=somevalue
I usually check that somename exists by doing:
if (isset($_GET['somename'])) {
However, I have seen a lot of people do this lately:
if ($_GET['somename'] != NULL) {
My question is, is either way better than the other?
Unlike the null check,
isset($_GET['somename']
will not throw an "undefined index" notice, so it's definitely the more preferable of the two.
array_key_exists("somename", $_GET);
would also be valid.
You may want to combine this with a null check however if you want to disallow empty values.
These statements are different.
isset() will check if a variable contains a value, whereas the second statement checks if the variable is equal to NULL or not.
In your case, use isset() to determine if $_GET['somename'] exists or not.
The best way is usually to do both. The isset checks if the variable exists, while you should also check to see if it is not NULL so that it won't break any later checks.
if(isset($_GET['somevalue']) && $_GET['somevalue'] != NULL)

Categories