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).
Related
I am trying to write a function to avoid getting variable undefined error. Right now, i have a code like this:
function check($str){
if(isset($str)){
$s = $str;
} else {
$s = "";
}
}
check($_GET['var']);
The get var is not set. I am getting a variable undefined error on my screen. How do i alter my function to not throw this error and just return "" if it is not set? I don't want to have to code 100 if statements to avoid getting variable undefined. Thanks.
We already have in PHP a construct to check that. It is called isset(). With it you can check whether a variable exists. If you would like to create it with some default values if it doesn't exist yet, we also have syntax for it. It's null-coalescing operator.
$_GET['var'] = $_GET['var'] ?? '';
// or since PHP 7.4
$_GET['var'] ??= '';
Although I'm not sure if it is the right way of doing it, for the sake of providing an answer you can pass the variable by reference, this allows you to get away with passing undefined variables and check if it is set inside the function..
function check(&$str){
if(!isset($str)){
$str = "not set";
}
}
check($_GET['var']);
echo $_GET['var'];
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.
In this snippet of code we type $inputs['user_id'] 3 times.
if (isset($inputs['user_id']) && $inputs['user_id']) { // The consumer is passing a user_id
doSomethingWith($inputs['user_id']);
}
What's the most readable and robust refactoring I can do to avoid the duplication and avoid any notice that the index user_id doesn't exist?
Thanks.
Here nothing is wrong with the duplication. You cannot assign $inputs['user_id'] to a variable before checking if it is set, otherwise this will produce a Notice undefined index ....
The only thing here could be done is to omit the isset call and use !empty instead, like this:
if(!empty($inputs['user_id'])) {
doSomething($inputs['user_id']);
}
Now You are only typing it twice and the check
!empty($inputs['user_id'])
equals to
isset($inputs['user_id']) && $inputs['user_id']
EDIT: based on a comments, here is a quote from documentation:
The following things are considered to be empty:
"" (an empty string)
0 (0 as an integer)
0.0 (0 as a float)
"0" (0 as a string)
NULL
FALSE
array() (an empty array)
$var; (a variable declared, but without a value)
So either empty(0) or empty('0') will return true, that means
if(!empty('0') || !empty(0)) { echo "SCREW YOU!"; }
will echo nothing... Or, in polite way, I will repeat the statement above:
!empty($inputs['user_id']) === (isset($inputs['user_id']) && $inputs['user_id'])
EDIT 2:
By omitting the isset and replacing by !empty the variable is still checked, whether the index is already set, please read the documentation, which says:
No warning is generated if the variable does not exist. That means empty() is essentially the concise equivalent to !isset($var) || $var == false.
What about this:
// put validation check to the function body
function doSomethingWith($userId) {
if($userId === -1) {
// if this is not a valid user id -> return
return;
}
// do something ...
}
// initalize $user with proper default values.
// doing so you can be sure that the index exists
$user = array(
'id' => -1,
'name' => '',
...
);
// merge inputs with default values:
$user = array_merge($user, $request);
// now you can just pass the value:
doSomethingWith($user['id']);
Below might not be the best way for every situation, but definitely cuts down on the repetition.
Your example code would turn into:
doSomethingWith($inputs['user_id']);
and your function would look like this (notice the argument supplied by reference, to avoid the undefined variable warning):
function doSomethingWith(&$userID) {
if (empty($userID)) return;
// ... actual code here ...
}
Assuming that 0 and "" and null are not valid user_ids:
if ($id = $inputs['user_id']) {
doer($id);
}
YOu can also do with evil # to avoid notice in your logs, (I don't like this way):
if ($id = #$inputs['user_id']) {
doer($id);
}
Dudes,
is there a more concise way to write the statement below? If I don't check if an array key exists I get a PHP warning. However, the below is a bit too, ehm, wordy.
Thanks!
$display_flag = false;
if (array_key_exists('display_flag',$pref_array) {
$display_flag = $pref_array['display_flag'];
}
Since PHP 7 you can use the new null coalescing operator.
$display_flag = $pref_array['display_flag'] ?? false;
If $display_flag is a boolean:
$display_flag = isset($pref_array['display_flag']) && $pref_array['display_flag'];
If it's a string:
$display_flag = isset($pref_array['display_flag']) ? $pref_array['display_flag'] : false;
// Get the $pref_array from wherever
$default_prefs = array(
"display_flag" => false,
);
$pref_array = array_merge($default_prefs, $pref_array);
// Now you know it's always defined with default values
The way you have it is fine, as you should validate if the value actually exists, but you could also do a ternary op:
$display_flag = (isset($pref_array['display_flag'])) ? (bool) $pref_array['display_flag'] : false;
I typecast the contents of display_flag to bool if it is set, so you are ensured a boolean value in either case.
Also you could (but I don't recommend it), squelch the warning with the #:
$display_flag = #$pref_array['display_flag'];
Another simpler option is:
array_get($variable, 'keyName', null)
The third argument is the default value.
Considering that:
The isset() construct returns TRUE if a variable is set and not NULL
The is_null() function throws a warning if the variable is not set
Is there a way to test whether a variable exists, no matter it's NULL or not, without using the # operator to suppress the notice?
EDIT
Together with your first replies, I've been thinking about this and I'm getting the conclusion that inspecting get_defined_vars() is the only way to distinguish between a variable set to NULL and an unset variable. PHP seems to make little distinctions:
<?php
$exists_and_is_null = NULL;
// All these are TRUE
#var_dump(is_null($exists_and_is_null));
#var_dump(is_null($does_not_exist));
#var_dump($exists_and_is_null===NULL);
#var_dump($does_not_exist===NULL);
#var_dump(gettype($exists_and_is_null)=='NULL');
#var_dump(gettype($does_not_exist)=='NULL');
?>
$result = array_key_exists('varname', get_defined_vars());
As you already found out, you cannot :
rely on isset, as it return false for a variable that's null.
use $not_exists===null, as it'll raise a notice.
But you could be able to use a combinaison of :
get_defined_vars to get the list of existing variables, including those which are null,
and array_key_exists to find out if an entry exists in that list.
For instance :
$exists_and_null = null;
$exists_and_not_null = 10;
$defined_vars = get_defined_vars();
// true
var_dump(array_key_exists('exists_and_null', $defined_vars)
&& $defined_vars['exists_and_null']===null);
// false
var_dump(array_key_exists('exists_and_not_null', $defined_vars)
&& $defined_vars['exists_and_not_null']===null);
// false
var_dump(array_key_exists('not_exists', $defined_vars)
&& $defined_vars['not_exists']===null);
A couple of notes :
In the first case, the variable exists => there is an entry in the list returned by get_defined_vars, so the second part of the condition is evaluated
and both parts of the condition are true
In the second case, the variable exists too, but is null
which means the first part of the condition is true, but the second one is false,
so the whole expression is false.
In the third case, the variable doesn't exist,
which means the first part of the condition is false,
and the second part of the condition is not evaluated -- which means it doesn't raise a notice.
But note this is probably not that a good idea, if you care about performances : isset is a language construct, and is fast -- while calling get_defined_vars is probably much slower ^^
I would argue here that any code requiring such a comparison would have gotten its semantics wrong; NULL is an unset value in a language that has no straightforward way of distinguishing between the two.
I used a self created function to check this easily, keep in mind it will fire off a PHP warning (I only monitor E_ERROR when I develop).
function isNullOrEmpty( $arg )
{
if ( !is_array( $arg ) )
{
$arg = array( $arg );
}
foreach ( $arg as $key => $value )
{
if( $value == null || trim($value) == "" )
{
return true;
}
}
return false;
}
if (isset($var) && (is_null($var)) {
print "\$var is null";
}
This should do the trick.