How does empty() work with a boolean expression? - php

A guy learning PHP sent me some code that has me scratching my head. He's getting $_POST input, putting it in variables, and then:
if( !empty($id && $name && $email) ) {
//do something
}
My first inclination was that passing multiple variables as an argument would throw an error, but it evaluates successfully. Am I incorrect that empty() should NOT take a boolean expression? Or - if I'm right - why does it work?

You can pass an expression to empty rather than a variable (since PHP 5.5), but with an expression like that you lose half of the benefit of using empty. empty checks that variables are set as well as evaluating their "truthiness". When you give it an expression like that, the individual variables within the expression are not checked to exist by empty. The expression is just evaluated as a boolean.
So if you used separate empty checks, you would get the check that the variables exist as well as the check that they are != false
if(!empty($id) && !empty($name) && !empty($email))
But when you use
if (!empty($id && $name && $email))
You will still get into the if block if all the variables are set and have non-false values, but you'll get undefined variable notices if any of them are not set. It's basically the same thing as not using empty at all, like this:
if ($id && $name && $email)
But if your guy is setting these variables from $_POST, they will be set, (if they weren't in $_POST he'd get undefined index warnings at that point) and the empty here is pointless anyway.

Related

unable to understand the behaviour of the isset and empty in the following form

I have a form with username and password and the value gets posted to check.php
when I have no input in username and password,(left blank), isset($_POST["username"]) and isset($_POST["password"]) returns true, which it should not be as I did not set anything.
But empty($_POST["username"] returns true as is expected.
can someone explain this behaviour of isset.
Thanks
If you submit form elements...
<input name='username'...
...but they're empty, it will fill the $_POST array with empty values by default. So, the variables are set, but they're empty ("").
What I usually do in this case is something like
if (isset($_POST['username'] && $_POST['username']) { ... }
In that case, it will check for if it's set (that is, is the form submitted) and if the values aren't empty. If they're empty ("") PHP will interpret as false and the condition will not be met.
That may be because your $_POST['username'] is set and may be empty, so to overcome check like this
if ((isset($_POST["username"]) && ($_POST["username"]!=""))
isset — Determine if a variable is set and is not NULL.
If a variable has been unset with unset(), it will no longer be set. isset() will return FALSE if testing a variable that has been set to NULL. Also note that a NULL byte ("\0") is not equivalent to the PHP NULL constant.
If multiple parameters are supplied then isset() will return TRUE only if all of the parameters are set. Evaluation goes from left to right and stops as soon as an unset variable is encountered.
refer :- http://php.net/manual/en/function.isset.php

PHP if (variable)

In various PHP tutorials I see this syntax -
if ($_POST) {
do something
}
I want to know whether this is equivalent to either isset or !(empty) (either one) or has different properties.
It attempts to evaluate the expression and cast it to boolean.
See 'Converting to boolean' at http://php.net/manual/en/language.types.boolean.php to see which values will be equivalent to true and which to false.
It does NOT however check for array key existence (i.e. isset), so if you try if ($_GET['somekey']) but somekey does not exist, you will see PHP Notice: Undefined index: somekey and then false will be assumed.
The best practice would be to perform empty() or isset() checks manually first as fits.
Good question. You are adressing one of PHPs dark sides if you ask me.
The if statement
Like in any other language I can imagine if evaluates the parameter to either true or false.
Since PHP doesn't really know types you could put any expression as parameter which will then be casted to bool as a whole
Following values are considered to be "FALSE"
boolean FALSE
integer 0
float 0.0
empty string
string "0"
any array with zero elements
NULL e.g. unset variables or $var = null
SimpleXML objects when created from empty tags
EVERY other value or expression result is casted to bool TRUE
Now, knowing this, all we need to find out is, what an expression or function returns when executed
If no POST data is set, the following expression would be TRUE
$_POST == FALSE
The isset function
isset returns bool TRUE when the given variable is set and not null.
parameters can be variables, array elements, string offsets and data members of objects.
In PHP 5.4 they fixed the behaviour with string offsets
$var = FALSE;
isset( $var ) === TRUE;
$var === FALSE;
More here
http://de1.php.net/manual/en/function.isset.php
The empty function
Returns false when a variable is considered to be empty or does not exist.
Those values are considered empty:
Returns FALSE if var exists and has a non-empty, non-zero value. Otherwise returns TRUE.
The following values are considered to be empty:
"" (empty string)
0 (integer)
0.0 (float)
"0" (string)
NULL
FALSE
array() (empty array)
Also declared variables without value are empty
compare table
$var = FALSE;
isset($var) === TRUE;
empty($var) === TRUE;
$var === FALSE;
if ($_POST)
This will evaluate to true if there are any elements in the POST array.
if(isset($_POST))
This will always evaluate to true because the POST array is always set, but may or may not contain elements, therefore it is not equivalent to the first example.
if(!empty($_POST))
This however, is equivalent to the first example because empty() checks for contents in the array.
A good generic way of testing if the page was posted to is:
if($_SERVER['REQUEST_METHOD'] == 'POST')
$_POST:
this is used to find whether data is passed on using HTTP POST method and also extracting the variables sent through the same which are collected in an associative array
isset:
checks whether a variable is set(defined) or is NULL(undefined)
PHP.net is an invaluable source of information for figuring out the intricacies and quirks of the language.
With that said, those are not equivalent. The if statement converts the expression to a boolean value (see here for information on what is considered false).
isset is used to "determine if a variable is set and is not NULL."
empty determines whether a variable is empty, i.e., "it does not exist or if its value equals FALSE."
Best practice if you want to check the value of a variable but you aren't sure whether it is set is to do the the following:
if(isset($var) && $var) { ... }
ie check isset() AND then check the variable value itself.
The reason for this is that if you just check the variable itself, as per the example in your question, PHP will throw a warning if the variable is not set. A warning message is not a fatal error, and the message text can be suppressed, but it's generally best practice to write code in such a way that it doesn't throw any warnings.
Calling isset() will only tell you whether a variable is set; it won't tell you anything about the value of the variable, so you can't rely on it alone.
Hope that helps.

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

PHP isset for submit form with or operator

Is it possible to add the "OR" operator to php isset submit form code when there are two submit buttons with different names?
Eg:
if (!isset($_POST['submitRequest'] || $_POST['submit']))
The above code prompts and an error. Please advice.
try:
if(isset($_POST['submitRequest']) || isset($_POST['submit'])){
//do something
}
No, it isn't possible. You need each variable in its own isset functioYou cannot combine them.
That's not how to use the or operator. You have to put it between two isset calls.
if ( ! isset($_POST['submitRequest']) || isset($_POST['submit']) ) { }
You always have to take a good look at the syntax. Remember that the or operator is used to make an entire condition evaluate to true if the left condition or the right condition is true. As such, you always need to use the or operator with two conditions.
Also, if you want to do this with the and operator, you can just use one isset call.
if ( isset($_POST['username'], $_POST['password']) ) { }
You need to call the isset function on respective variables individually. You have an option of using either of the two syntax, depending on the convention you follow.
if(isset($_POST['submitRequest']) || isset($_POST['submit'])){
//do something
}
if(isset($_POST['submitRequest']) OR isset($_POST['submit'])){
//do something
}
You can use isset() on multiple variables:
if(isset($_POST['submitRequest']) || isset($_POST['submit'])) {
// One of them was pushed
}
Be careful when passing multiple arguments to isset(). As the manual documents:
If multiple parameters are supplied then isset() will return TRUE only if all of the parameters are set. Evaluation goes from left to right and stops as soon as an unset variable is encountered.
So isset($_POST['submitRequest'], $_POST['submit']) would be the equivalent of isset($_POST['submitRequest']) && isset($_POST['submit']). However, that second sentence can be useful if you want to check !isset($_POST['submitRequest']) || !isset($_POST['submit']). Since when passed multiple arguments, isset() will return false for the first unset one, you can use !isset($_POST['submitRequest'], $_POST['submit']).
to elaborate a bit:
isset(), empty() and a few other are not functions, but language constructs. As such, they don't work in all the ways one might expect according to them looking like functions.
The important part here is: they only check variables, they can't and don't evaluate the results of expressions.
The use of || makes $_POST['submitRequest'] || $_POST['submit'] an expression. The result is only calculated temporarily, not stored in defined variable which can be set or empty.
I know I had misunderstood the original post.
if(isset($_POST['submitRequest'])||isset($_POST['submit'])){
// you can do something here
}
Original (incorrect)
You can use this:
if(!isset($_POST['submitRequest'], $_POST['submit'])){
die("Fail");
}
If multiple parameters are supplied, the function will check all of them. This will return TRUE only if all of the parameters are set.
Reference: http://php.net/manual/en/function.isset.php

PHP in_array not working

I am using the PHP in_array() function in order to authenticate (with sessions) if a user can access a particular page. For some reason, it is not working...
PHP PAGE
session_start();
require_once('../scripts/functions.php');
$role_auth = #$_SESSION['role_auth'];
access($role_auth, array(0,1,2,3,4));
access FUNCTION
function access($role_auth, $array){
if(!(in_array($role_auth, $array))){
header("Location: ../index.html");
}
}
If I insert print statements in the function, I can see that all of the correct values are being passed into the function. The problem is, if the function is called without a session variable set, for some reason it is considered as being in the array, and it authenticates.
Any ideas?
you may want to enable strict type checks by using:
in_array($role_auth, $array, true)
as what is likely happening is that $role_auth is being eval'd as false and that could match 0 in your in_array statement.
what you SHOULD be doing is this:
session_start();
require_once('../scripts/functions.php');
$role_auth = (isset($_SESSION['role_auth']))?$_SESSION['role_auth']:-1;
access($role_auth, array(0,1,2,3,4));
or something similiar. nothing good ever comes of using the # operator
I would check to see if $_SESSION['role_auth'] is actually set (with isset) instead of using # to suppress warnings (which is bad practice IMHO)
I think what's happening is that false == 0 ... so in_array returns true when nothing is in $role_auth because it sees it as 0 and 0 is in your array
$role_auth = #$_SESSION['role_auth'];
The # sign is suppressing any warnings you might get here, like index is not in array. How about something like this instead:
if(isset($_SESSION['role_auth']))
$role_auth = $_SESSION['role_auth'];
else
$role_auth = -1;//(or whatever an invalid role is)
In php, the number zero is considered equal to most non-numeric things, for example:
null == 0
false == 0
"" == 0
"asdf" == 0
You probably need to make sure that $_SESSION actually contains the 'role_auth' key beforehand and convert it to the appropriate type, also passing the $strict parameter to in_array, thus guaranteeing a type check as well as a value check (=== vs. ==). Removing zero from your array might also be a good idea.

Categories