PHP - refactoring this if statement to avoid duplication - php

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);
}

Related

PHP: is empty($var) equivalent to !$var

For validating a variable value we can do
if(empty($var)){
}
OR
This will return true on empty string, 0 as number, false, null
if(!$var){
}
What is the difference between this two approaches, are them equivalent?
EDIT: Some examples where they behave different will be more pratical.
EDIT2: The only difference founded from answers is that the second will throw a notice if $var is undefined. What about the boolean value they return?
EDIT3: for $var I mean any variable with any value, or even an undefined variable.
Conclusion from users answers:
if(!$var) and empty($var) are equivalent as described here http://php.net/manual/en/types.comparisons.php, they will return the same bool value on the same variable.
if(!$var) will return a php notice if $var is not defined, normally this is not the case (if we write good code) most IDEs will underline it.
When checking simple variables if(!$var) should be ok
When checking arrays index ($var['key']) or object properties ($var->key)
empty($var['key']) is better using empty.
the problem is that since !$vars is shorter than empty($vars) many of us will prefer the first way
You prefer the first one because it is a "shorter way"?
Shorter code does not mean better code, or faster scripts ;)
The speed of PHP functions and its various other behaviours is not determined by the length of the function name. It is determined by what PHP is actually doing to evaluate, action, and return results.
Besides that, don't choose methods based on length of code, choose methods based on scenario and best approach "for a given scenario".
Which is best depends on what you need, and there are other variable checks other than the two you mentioned (isset() for one).
but the problem is are they equivalent always
Not necessarily - see
http://php.net/manual/en/types.comparisons.php
Or create a quick test script to see what PHP returns for your two scenarios.
You could also be initialising your variables in your framework (or, likely, stand alone script), which means the scenario changes, as could your question and approach you use.
It's all contextual as to which is the best.
As for the required answer.
Anyway, to answer your question, here are some tests:
(!$vars)
Example code:
if ( !$vars )
{
echo "TRUE";
}
else
{
echo "FALSE";
}
will return:
Notice: Undefined variable: vars in /whatever/ on line X
TRUE
However, if you initialise the var in your scripts somewhere first:
$vars = "";
$vars = NULL;
$vars = 0;
Any of the above will return:
[no PHP notice]
TRUE
$vars = "anything";
will return:
FALSE
This is because with the exclamation mark you are testing if the var is FALSE, so when not initialised with a string the test script returns TRUE because it is NOT FALSE.
When we initialise it with a string then the var NOT being FALSE is FALSE.
empty($vars)
Example code:
if ( empty($vars) )
{
echo "TRUE";
}
else
{
echo "FALSE";
}
Not initialised/set at all, and all of the following:
$vars = "";
$vars = NULL;
$vars = 0;
will return:
TRUE
There is no PHP notice for using empty, so here we show a difference between the two options (and remember when I said the shortest code is not necessarily the "best"? Depends on the scenario etc.).
And as with the previous test:
$vars = "anything";
returns:
FALSE
This is the same with ( !$var ), you are testing IF EMPTY, and without the var being initialised at all, or with any "empty()" value: eg (""), or NULL, or zero (0), then testing if the var is empty is TRUE, so we get TRUE output.
You get FALSE when setting the var to a string because IS EMPTY = FALSE as we set it to something.
The difference is empty() does not throw a PHP notice when var is not defined, whereas (!$var) will.
Also, you may prefer it for being "shorter code", but if (!$var) isn't really much shorter/better looking than the widely used if (empty($var)).
But again, this depends on the scenario - PHP provides different options to suit different requirements.
No they are not equal
if(empty($var)){
echo "empty used\n";
}
if(!$var){ # line no. 6
echo "! used";
}
will output
empty used
Notice: Undefined variable: var in /var/www/html/test.php on line 6
! used
Following values are considered to be empty when using empty() function
"" (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)
As you can read in empty docs
empty() is essentially the concise equivalent to !isset($var) || $var
== false.
They are not.
The first one verify if $var has any value.
The second one verify as boolean - if true or not.
The second one will give you a notice, the first one will be true if the value is empty for $var.
If you wish to verify if $var exists, use isset.
if( !isset($var) )
echo '$var does not exists!<br>';
if(empty($var))
echo 'The value is empty or does not exists!<br>';
if( !$var )
echo 'Value is false!<br>';
$var = '';
if(empty($var))
echo 'The value is empty or does not exists!<br>';
Use this to view the notice
error_reporting(-1);
ini_set('display_errors', 1);
The main difference is that empty() will not complain if the variable does not exist, whereas using ! will generate a warning.
In older versions of PHP, empty() only worked on direct variables, meaning this would fail:
empty($a && $b);
This has been changed in 5.5
The official manual contains all you have to know on this subject:
http://php.net/manual/en/types.comparisons.php
if (!$var) is the last column, boolean : if($x) negated.
As you can see they are the same, but empty won't complain if the variable wasn't set.
From the manual:
empty() does not generate a warning if the variable does not exist
Take some time, and study that chart.
As far as I know, it's pretty simple.
empty() is basically equivalent to !isset($var) || !$var and does not throw any warnings/notices, whereas using just !$var will throw a notice if the variable isn't defined.
For the sake of completeness, the following are considered empty when using empty():
empty strings
empty arrays
0, 0.0, '0' (int, float, string)
null
false
defined variables without a value
From a boolean value return empty is equivaliend to !:
empty($var) === !$var; // supposed that $vars has been defined here
From a notice/waning notification they are not equivalent:
empty($array['somekey']); //will be silent if somekey does not exists
!$array['somekey']; // will through a warning if somekey does not exists

Checking for a null value in conditional in PHP

I have found there to be multiple ways to check whether a function has correctly returned a value to the variable, for example:
Example I
$somevariable = '';
$somevariable = get_somevariable();
if ($somevariable)
{
// Do something because $somevariable is definitely not null or empty!
}
Example II
$somevariable = '';
$somevariable = get_somevariable();
if ($somevariable <> '')
{
// Do something because $somevariable is definitely not null or empty!
}
My question: what is the best practice for checking whether a variable is correct or not? Could it be different for different types of objects? For instance, if you are expecting $somevariable to be a number, would checking if it is an empty string help/post issues? What is you were to set $somevariable = 0; as its initial value?
I come from the strongly-typed world of C# so I am still trying to wrap my head around all of this.
William
It depends what you are looking for.
Check that the Variable is set:
if (isset($var))
{
echo "Var is set";
}
Checking for a number:
if (is_int($var))
{
echo "Var is a number";
}
Checking for a string:
if (is_string($var))
{
echo "var is a string";
}
Check if var contains a decimal place:
if (is_float($var))
{
echo "Var is float";
}
if you are wanting to check that the variable is not a certain type, Add: ! an exclamation mark. Example:
if (!isset($var)) // If variable is not set
{
echo "Var Is Not Set";
}
References:
http://www.php.net/manual/en/function.is-int.php
http://www.php.net/manual/en/function.is-string.php
http://www.php.net/manual/en/function.is-float.php
http://www.php.net/manual/en/function.isset.php
There is no definite answer since it depends on what the function is supposed to return, if properly documented.
For example, if the function fails by returning null, you can check using if (!is_null($retval)).
If the function fails by returning FALSE, use if ($retval !== FALSE).
If the function fails by not returning an integer value, if (is_int($retval)).
If the function fails by returning an empty string, you can use if (!empty($retval)).
and so on...
It depends on what your function may return. This kind of goes back to how to best structure functions. You should learn the PHP truth tables once and apply them. All the following things as considered falsey:
'' (empty string)
0
0.0
'0'
null
false
array() (empty array)
Everything else is truthy. If your function returns one of the above as "failed" return code and anything else as success, the most idiomatic check is:
if (!$value)
If the function may return both 0 and false (like strpos does, for example), you need to apply a more rigorous check:
if (strpos('foo', 'bar') !== false)
I'd always go with the shortest, most readable version that is not prone to false positives, which is typically if ($var)/if (!$var).
If you want to check whether is a number or not, you should make use of filter functions.
For example:
if (!filter_var($_GET['num'], FILTER_VALIDATE_INT)){
//not a number
}

Test for NULL value in a variable that may not be set

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.

php: check if certain item in an array is empty

In PHP, how would one check to see if a specified item (by name, I think - number would probably also work) in an array is empty?
Types of empty (from PHP Manual). The following are considered empty for any variable:
"" (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)
So take the example below:
$arr = array(
'ele1' => 'test',
'ele2' => false
);
1) $arr['ele3'] is not set. So:
isset($arr['ele3']) === false && empty($arr['ele3']) === true
it is not set and empty. empty() checks for whether the variable is set and empty or not.
2) $arr['ele2'] is set, but empty. So:
isset($arr['ele2']) === true && empty($arr['ele2']) === true
1) $arr['ele1'] is set and not empty:
isset($arr['ele1']) === true && empty($arr['ele1']) === false
if you wish to check whether is it empty, simply use the empty() function.
if(empty($array['item']))
or
if(!isset($array['item']))
or
if(!array_key_exists('item', $array))
depending on what precisely you mean by "empty". See the docs for empty(), isset() and array_key_exists() as to what exactly they mean.
<?php
$myarray=array(1,5,6,5);
$anotherarray=array();
function checkEmpty($array){
return (count($array)>0)?1:0;
}
echo checkEmpty($myarray);
echo checkEmpty($anotherarray);
?>
(for checking if empty result 1 else 0);
Compactness is what I persue in my code.
i had such situation where i was getting tab it last index of array so if put things together then this might work for the most of cases
<?php
if( ctype_space($array['index']) && empty($array['index']) && !isset($array['index']) ){
echo 'array index is empty';
}else{
echo 'Not empty';
}

Better way to check variable for null or empty string?

Since PHP is a dynamic language what's the best way of checking to see if a provided field is empty?
I want to ensure that:
null is considered an empty string
a white space only string is considered empty
that "0" is not considered empty
This is what I've got so far:
$question = trim($_POST['question']);
if ("" === "$question") {
// Handle error here
}
There must be a simpler way of doing this?
// Function for basic field validation (present and neither empty nor only white space
function IsNullOrEmptyString($str){
return ($str === null || trim($str) === '');
}
Old post but someone might need it as I did ;)
if (strlen($str) == 0){
do what ever
}
replace $str with your variable.
NULL and "" both return 0 when using strlen.
Use PHP's empty() function. 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)
For more details check empty function
I'll humbly accept if I'm wrong, but I tested on my own end and found that the following works for testing both string(0) "" and NULL valued variables:
if ( $question ) {
// Handle success here
}
Which could also be reversed to test for success as such:
if ( !$question ) {
// Handle error here
}
Beware false negatives from the trim() function — it performs a cast-to-string before trimming, and thus will return e.g. "Array" if you pass it an empty array. That may not be an issue, depending on how you process your data, but with the code you supply, a field named question[] could be supplied in the POST data and appear to be a non-empty string. Instead, I would suggest:
$question = $_POST['question'];
if (!is_string || ($question = trim($question))) {
// Handle error here
}
// If $question was a string, it will have been trimmed by this point
There is no better way but since it's an operation you usually do quite often, you'd better automatize the process.
Most frameworks offer a way to make arguments parsing an easy task. You can build you own object for that. Quick and dirty example :
class Request
{
// This is the spirit but you may want to make that cleaner :-)
function get($key, $default=null, $from=null)
{
if ($from) :
if (isset(${'_'.$from}[$key]));
return sanitize(${'_'.strtoupper($from)}[$key]); // didn't test that but it should work
else
if isset($_REQUEST[$key])
return sanitize($_REQUEST[$key]);
return $default;
}
// basics. Enforce it with filters according to your needs
function sanitize($data)
{
return addslashes(trim($data));
}
// your rules here
function isEmptyString($data)
{
return (trim($data) === "" or $data === null);
}
function exists($key) {}
function setFlash($name, $value) {}
[...]
}
$request = new Request();
$question= $request->get('question', '', 'post');
print $request->isEmptyString($question);
Symfony use that kind of sugar massively.
But you are talking about more than that, with your "// Handle error here
". You are mixing 2 jobs : getting the data and processing it. This is not the same at all.
There are other mechanisms you can use to validate data. Again, frameworks can show you best pratices.
Create objects that represent the data of your form, then attach processses and fall back to it. It sounds far more work that hacking a quick PHP script (and it is the first time), but it's reusable, flexible, and much less error prone since form validation with usual PHP tends to quickly become spaguetti code.
This one checks arrays and strings:
function is_set($val) {
if(is_array($val)) return !empty($val);
return strlen(trim($val)) ? true : false;
}
to be more robust (tabulation, return…), I define:
function is_not_empty_string($str) {
if (is_string($str) && trim($str, " \t\n\r\0") !== '')
return true;
else
return false;
}
// code to test
$values = array(false, true, null, 'abc', '23', 23, '23.5', 23.5, '', ' ', '0', 0);
foreach ($values as $value) {
var_export($value);
if (is_not_empty_string($value))
print(" is a none empty string!\n");
else
print(" is not a string or is an empty string\n");
}
sources:
https://www.php.net/manual/en/function.is-string.php
https://www.php.net/manual/en/function.trim.php
When you want to check if a value is provided for a field, that field may be a string , an array, or undifined. So, the following is enough
function isSet($param)
{
return (is_array($param) && count($param)) || trim($param) !== '';
}
use this :
// check for null or empty
if (empty($var)) {
...
}
else {
...
}
empty() used to work for this, but the behavior of empty() has changed several times. As always, the php docs are always the best source for exact behavior and the comments on those pages usually provide a good history of the changes over time. If you want to check for a lack of object properties, a very defensive method at the moment is:
if (is_object($theObject) && (count(get_object_vars($theObject)) > 0)) {

Categories