I'm wondering if there is a more elegant way to do this:
$foo = (isset($bar) and array_key_exists('meh', $bar)) ? $bar['meh'] : '';
If I remove the isset part, PHP issues a warning if $bar isn't an array, if I remove the array_key_exists part, PHP issues a warning if the meh key isn't in the array. Is there a more graceful, warning free, way of achieving the same end?
You take exactly the steps required to "secure" code against the warnings you mention.
However, the warnings are there for a reason. Typically it makes more sense to check, if you can prevent situations where the variables you are trying to access are not initialized.
You can reference the key directly. Inside isset it won't even throw an exception if $bar is undefined.
$foo = isset($bar['meh']) ? $bar['meh'] : '';
The difference between array_key_exists and isset is that isset will return FALSE if the key corresponds to a NULL value. In my code above, a NULL value will therefore result in $foo begin the empty string, not NULL. If that is a problem your current approach will be the best.
Related
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.
There is an example in PHP Object-Oriented Solutions that seems to be flawed, if I understand is_null properly.
The sample code in the book is as follows:
if (!is_null($required) && !is_array($required)) {
throw new Exception('The names of required fields must be an array, even if only one field is required.');
}
This code is supposed to test that a var $required is not NULL and is an array. To my understanding, is_null() returns TRUE if the variable is not set or is NULL. So, does it make sense to negate is_null() in that example if you're trying to throw an exception when the variable is not set, NULL, or is not an array? The only way an exception is thrown is if (true && true) is satisfied.
FROM: http://www.php.net/manual/en/language.types.null.php
A variable is considered to be null if:
it has been assigned the constant NULL.
it has not been set to any value yet.
it has been unset().
<?php
if(is_null($obj)){
echo 'is null';
}
While $obj is considered NULL because it hasn't been registered yet, it will still throw a Notice: undefined ...
The correct use for your if statement should first check to see if the variable exists then check to see if it is an array.
if (!isset($required) || !is_array($required)) {}
-or-
if (empty($required) || !is_array($required)) {}
The nice thing about is_array() is the fact that if $required IS NULL then it's not an array and will pass the if clause.
isset() and empty() will both ensure that the variable exists. Failure to pass either of these methods will quit the if statement and no errors will be returned.
I appreciate all the feedback, but somehow I think part of my question was not addressed. The fact that the variable is being tested with a Logical AND, means that both statements must be TRUE for the Exception in the if clause to run.
But, I don't think the use of !is_null($required) is correct. The sample code from the book was testing for a variable to contain an array with one to many values. Even if it has one value, the $required variable (for other reasons) still must be declared as an array with a single value. So, if $required hold's a value of (int) 5, an Exception should be thrown. If the $required variable is not declared/instantiated, an Exception should be thrown. If the $required variable holds NULL, an Exception should be thrown. Here is where the logic of this sample code fails. Using the online php command line that #Calimero posted, this logic fails when $required is set to NULL.
Instead of using !is_null($required) , is_null($required) without the negation should have been used since is_null returns TRUE if the value of $required is indeed NULL. So, if you negate is_null() when the $required value happens to be NULL, that part of the logical AND operation becomes FALSE, therefore the Exception never gets run at all because the logical AND operation requires both statements to be TRUE for the logic to jump into the curly braces. Which is precisely what the if clause was supposed to catch in the first place. The sample code was supposed to catch the $required variable not being set and not being of an array type.
And as I mentioned in a comment, isset() probably wasn't used because isset will return TRUE even if the $required variable is an empty string, a string with a space, an empty array, etc.
Someone please confirm I'm not talking stupid. LOL.
Take a look at this: (http://3v4l.org/QpVXq)
**Is_null**
The is_null is php construct language and can be used to test whether a variable is set to null.
$myVariable = null;
is_null($myVariable); // this returns true,because it is set to null
$myVariable = 10;
is_null($myVariable); // this returns false, cuz it is assigned to value
If the variable does not exist is_null will also return true,
but with an error notice as it is not supposed
to be used with uninitialized variables.
//returns true and also notice with (undefined variable notice)
is_null($myNewVariable);// true (undefined variable notice)
If the code is part of a function, it could be that the function allows for null values, but if the value is passed and it's not an array, then an exception must be thrown. If the code is not part of a function, it may be just demonstrating how to detect if a value is an array only if it isn't null, thus allowing null values.
I have code that is used very extensively which fetches an array from another method, and sometimes returns the first element of that array. Given that null is an acceptable return value for the function, is it worth the performance overhead of calling isset() on the array index (or checking the array length, etc), or is it better to just return the non-existant index (warnings aside). What are the advantages of calling isset() aside from preventing the warning.
The example below is simplified, the real function doesn't just get the first element of the array.
Return index which may not exist:
function get_array_element(){
$array = get_array(); // function that returns array
return $array[0]; // return index 0 which may not exist
}
Versus checking if index is set:
function get_array_element(){
$array = get_array(); // function that returns array
return (isset($array[0]))? // check if index 0 isset() else return null
$array[0] :
null;
}
Throwing a notice when accessing an undefined index -- in theory -- should alert you for typos in key names. In practice, if you’re using isset first, you probably just copied the key name there. Or used a numeric index. Or a constant.
On the other hand, in most cases you’re accessing an index withour caring wether it’s set or not -- and in this scenario, using isset is just anoying. A lot of languages lets you just retrieve any index without warnings, Javascript for example: just returning an undefined.
So I would advice to ignore the notice. Not all of them, because in some cases there really are helpful, so keep them turned on in development, but silence such array access by using #. Yes, it is ugly, but does its job:
return #$array[0];
Or in simple cases, maybe other solutions fit?
return array_shift($array);
Calling isset inside that function is semi-pointless because you are returning null if it doesn't exist, but null will be returned from $array[0] regardless of whether you use isset of not.
If it only throws an E_NOTICE then I wouldn't worry about it, just check for get_array_element() == null.
so if I have this code:
$bla = 1;
if($foo && $bla) do_whatever...
I get a notice telling me that $foo is a undefined variable.
So I have to change my code to this:
$bla = 1;
if(isset($foo) && $foo && $bla) do_whatever...
Is there anyway I can avoid checking if a variable is assigned and just assume the variable is false, but without having to turn off PHP notices?
Depending on the exact behavior you want, you can check if the variable is empty():
Returns FALSE if var has a non-empty
and non-zero value.
The following things are considered to
be empty:
"" (an empty string) 0 (0 as an
integer) "0" (0 as a string) NULL
FALSE array() (an empty array) var
$var; (a variable declared, but
without a value in a class)
It's important to understand all those cases, but it's handy language construct. if $foo is undefined if($foo) will throw a notice, but if(!empty($foo)) will not -- the expression will evaluate to false
This should not be abused, however. As others have stated, those notices are for your protection, so if you can define your variables, you should do so. Where empty() comes in especially handy is things like if (!empty($_GET['foo'])) - testing for the existence of input in superglobals.
The entire point of notices is to tell you that something might be wrong (such as writing $fooo instead of $foo). So, if you're not going to use them, you might as well disable them. You can disable a notice selectively by setting your own error handler, and discarding the error silently when it's of the "undefined variable" kind.
Of course, the clean thing to do would be to define your variables in the first place.
No, there isn't.
No, you should always know exactly what's going on with your variables. In fact, you should never need to use isset() on a variable itself at all.
You could do:
if(#$foo && $bla) do_whatever...
The # will suppress the warning.
But you really shouldn't do it. Not checking ALL your input is just plain WRONG.
In a php page I have following code:
if($_REQUEST['c']!="") // I get error on this line itself. Why?
{
$pidis=(int)($_REQUEST['c']);
}
I keep getting Undefined index error.
On Googling I manage to understand that if a page is access without parameters (in URL) which we are trying to access we can get this error/warning. I believe that if a parameter is not defined in the URL it should just return empty instead of giving error/warning message.
I know that it is possible to suppress errors and warning by adding
error_reporting(E_ALL ^ E_NOTICE);
But I do not want to do this.
This same page work just fine on our company's web server but does not work on our clients web server.
Why is this happening?
How to solve this problem?
You are getting that error because you are attempting to compare $_REQUEST['c'] to something when $_REQUEST['c'] does not exist.
The solution is to use isset() before comparing it. This will remove the warning, since the comparison won't happen if $_REQUEST['c'] doesn't exist.
if(isset($_REQUEST['c']) && $_REQUEST['c']!="")
{
$pidis=(int)($_REQUEST['c']);
}
It is an E_NOTICE level error, and your level of error reporting will affect whether the error shows up or not. Your client's server has E_NOTICE level error reporting turned on, which is why it shows up there.
It is a good idea to always develop using E_ALL so that you can catch this kind of error before moving your code to other servers.
Another solution is to use the following:
$pidis = isset($_REQUEST['c']) ? $_REQUEST['c'] : '';
You can also, if you prefer to return a value other than empty, by placing a default value within the final set of single quotes, e.g.
$pidis = isset($_REQUEST['c']) ? $_REQUEST['c'] : 'Default Value';
or return a different variable type, for instance an integer:
$pidis = isset($_REQUEST['c']) ? $_REQUEST['c'] : 34;
Instead of isset() you can also use: array_key_exists().
The difference between both methods is that isset() checks also whether the value of the variable is null. If it is null then isset returns false whereas array_key_exists() returns always true if the key exists (no mater which value). E.g.:
$array = array('c' => null);
var_dump(isset($array['c']))); // isset() returns FALSE here
var_dump(array_key_exists($array['c']); //array_key_exists() returns TRUE
Depending on the context, it is important to distinguish this. In your case I don't think it matters doesn't matter, as (I guess) a request parameter never will be null (except one overwrites it manually).
Use isset($_REQUEST['c']) to test if it exists first.
PHP is giving a notice (which is not an error : it's just a notice) when you are trying to use a variable that doesn't exists, or an array element that doesn't exist.
This is just to help you, and you should not mask those notices : they are here to help you -- for instance, to help you detect typos in variable names.
Before using that array index, if it's not always present, you should test if it's here, using isset :
if (isset($_REQUEST['c']) && $_REQUEST['c']!="") {
// ...
}
Clean way could be :
$pidis = $_REQUEST['c'] ?? null
this is same as checking isset request but shorter.