Is this conditional check overkill? - php

$result = validateUploadedFile($_FILES);
if (!empty($result) && !empty($result['valid']) && $result['valid'])
{
// do sth
// I don't know why sometime this three checks will cause me problems
// In other words, even if $result['valid'] is TRUE, this scope will not be hit
}
The function validateUploadedFile returns an array as $result['valid'] == TRUE if it goes through.
Here is the question, does the if statement checks too much?
Can I simply check the following instead? I have few PHP language knowledge and don't know whether those checks are necessary or not.
if ( $result['valid'] )
{
// do sth
}
Thank you
function validateUploadedFile($uploadedFile)
{
// Define file size limit
$result = array('valid' => FALSE, 'error_message' => null, 'error_code' => null);
if (sth_wrong)
{
$result['error_message'] = 'sth_wrong';
return $result;
}
if (sth_wrong2)
{
$result['error_message'] = 'sth_wrong2';
return $result;
}
$result['valid'] = TRUE;
return $result;
}

It depends on what the function returns in the case where the uploaded file is not valid. This should probably suffice in most cases though:
if (!empty($result['valid']))
Since:
FALSE is empty
NULL (or an unset array index) is empty
It won't complain, even if $result is an empty array
You could also just do
if (!$result['valid'])
but this will give you E_NOTICE if that element isn't set.

I would think
if (isset($result['valid']) && $result['valid'])
would work just fine.

Your approach is more of what you should be doing with raw user input. Since you're dealing with a function, however, it would be a lot easier to have it do the heavy lifting.
Just ensure it always sets the 'valid' key; your code will be more readable and secure. If you do that, an if($result['valid']) will suffice.

You can test it. In this particular case, it seems you're not entirely sure which values to check for. In most cases and according to logic, simply doing a !$result['valid'] /should/ work - but that's assuming PHP considers null / unset values as 'false'.
Make a quick script that tests all the conditions separately.
What happens when calling empty($result['valid']) when $result is null?
What happens when calling !$result['valid'] when $result['valid'] is undefined?
Go on. Write a script. Test it, and Know.

Related

initialize a PHP variable if not set [duplicate]

I have several older applications that throw a lot of "xyz is undefined" and "undefined offset" messages when running on the E_NOTICE error level, because the existence of variables is not explicitly checked using isset() and consorts.
I am considering working through them to make them E_NOTICE compatible, as notices about missing variables or offsets can be lifesavers, there may be some minor performance improvements to be gained, and it's overall the cleaner way.
However, I don't like what inflicting hundreds of isset() empty() and array_key_exists() s does to my code. It gets bloated, becomes less readable, without gaining anything in terms of value or meaning.
How can I structure my code without an excess of variable checks, while also being E_NOTICE compatible?
For those interested, I have expanded this topic into a small article, which provides the below information in a somewhat better structured form: The Definitive Guide To PHP's isset And empty
IMHO you should think about not just making the app "E_NOTICE compatible", but restructuring the whole thing. Having hundreds of points in your code that regularly try to use non-existent variables sounds like a rather badly structured program. Trying to access non-existent variables should never ever happen, other languages balk at this at compile time. The fact that PHP allows you to do it doesn't mean you should.
These warnings are there to help you, not to annoy you. If you get a warning "You're trying to work with something that doesn't exist!", your reaction should be "Oops, my bad, let me fix that ASAP." How else are you going to tell the difference between "variables that work just fine undefined" and honestly wrong code that may lead to serious errors? This is also the reason why you always, always, develop with error reporting turned to 11 and keep plugging away at your code until not a single NOTICE is issued. Turning error reporting off is for production environments only, to avoid information leakage and provide a better user experience even in the face of buggy code.
To elaborate:
You will always need isset or empty somewhere in your code, the only way to reduce their occurrence is to initialize your variables properly. Depending on the situation there are different ways to do that:
Function arguments:
function foo ($bar, $baz = null) { ... }
There's no need to check whether $bar or $baz are set inside the function because you just set them, all you need to worry about is if their value evaluates to true or false (or whatever else).
Regular variables anywhere:
$foo = null;
$bar = $baz = 'default value';
Initialize your variables at the top of a block of code in which you're going to use them. This solves the !isset problem, ensures that your variables always have a known default value, gives the reader an idea of what the following code will work on and thereby also serves as a sort of self-documentation.
Arrays:
$defaults = array('foo' => false, 'bar' => true, 'baz' => 'default value');
$values = array_merge($defaults, $incoming_array);
The same thing as above, you're initializing the array with default values and overwrite them with actual values.
In the remaining cases, let's say a template where you're outputting values that may or may not be set by a controller, you'll just have to check:
<table>
<?php if (!empty($foo) && is_array($foo)) : ?>
<?php foreach ($foo as $bar) : ?>
<tr>...</tr>
<?php endforeach; ?>
<?php else : ?>
<tr><td>No Foo!</td></tr>
<?php endif; ?>
</table>
If you find yourself regularly using array_key_exists, you should evaluate what you're using it for. The only time it makes a difference is here:
$array = array('key' => null);
isset($array['key']); // false
array_key_exists('key', $array); // true
As stated above though, if you're properly initializing your variables, you don't need to check if the key exists or not, because you know it does. If you're getting the array from an external source, the value will most likely not be null but '', 0, '0', false or something like it, i.e. a value you can evaluate with isset or empty, depending on your intent. If you regularly set an array key to null and want it to mean anything but false, i.e. if in the above example the differing results of isset and array_key_exists make a difference to your program logic, you should ask yourself why. The mere existence of a variable shouldn't be important, only its value should be of consequence. If the key is a true/false flag, then use true or false, not null. The only exception to this would be 3rd party libraries that want null to mean something, but since null is so hard to detect in PHP I have yet to find any library that does this.
Just write a function for that. Something like:
function get_string($array, $index, $default = null) {
if (isset($array[$index]) && strlen($value = trim($array[$index])) > 0) {
return get_magic_quotes_gpc() ? stripslashes($value) : $value;
} else {
return $default;
}
}
which you can use as
$username = get_string($_POST, 'username');
Do the same for trivial stuff like get_number(), get_boolean(), get_array() and so on.
I believe one of the best ways of coping with this problem is by accessing values of GET and POST (COOKIE, SESSION, etc.) arrays through a class.
Create a class for each of those arrays and declare __get and __set methods (overloading). __get accepts one argument which will be the name of a value. This method should check this value in the corresponding global array, either using isset() or empty() and return the value if it exists or null (or some other default value) otherwise.
After that you can confidently access array values in this manner: $POST->username and do any validation if needed without using any isset()s or empty()s. If username does not exist in the corresponding global array then null will be returned, so no warnings or notices will be generated.
I don't mind using the array_key_exists() function. In fact, I prefer using this specific function rather than relying on hack functions which may change their behavior in the future like empty and isset (strikedthrough to avoid susceptibilities).
I do however, use a simple function that comes handy in this, and some other situations in dealing with array indexes:
function Value($array, $key, $default = false)
{
if (is_array($array) === true)
{
settype($key, 'array');
foreach ($key as $value)
{
if (array_key_exists($value, $array) === false)
{
return $default;
}
$array = $array[$value];
}
return $array;
}
return $default;
}
Let's say you've the following arrays:
$arr1 = array
(
'xyz' => 'value'
);
$arr2 = array
(
'x' => array
(
'y' => array
(
'z' => 'value',
),
),
);
How do you get the "value" out of the arrays? Simple:
Value($arr1, 'xyz', 'returns this if the index does not exist');
Value($arr2, array('x', 'y', 'z'), 'returns this if the index does not exist');
We already have uni and multi-dimensional arrays covered, what else can we possibly do?
Take the following piece of code for instance:
$url = 'https://stackoverflow.com/questions/1960509';
$domain = parse_url($url);
if (is_array($domain) === true)
{
if (array_key_exists('host', $domain) === true)
{
$domain = $domain['host'];
}
else
{
$domain = 'N/A';
}
}
else
{
$domain = 'N/A';
}
Pretty boring isn't it? Here is another approach using the Value() function:
$url = 'https://stackoverflow.com/questions/1960509';
$domain = Value(parse_url($url), 'host', 'N/A');
As an additional example, take the RealIP() function for a test:
$ip = Value($_SERVER, 'HTTP_CLIENT_IP', Value($_SERVER, 'HTTP_X_FORWARDED_FOR', Value($_SERVER, 'REMOTE_ADDR')));
Neat, huh? ;)
Welcome to null coalescing operator (PHP >= 7.0.1):
$field = $_GET['field'] ?? null;
PHP says:
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.
I'm here with you. But PHP designers has made a lot more worse mistakes than that. Short of defining a custom function for any value reading, there isn't any way around it.
I use these functions
function load(&$var) { return isset($var) ? $var : null; }
function POST($var) { return isset($_POST[$var]) ? $_POST[$var] : null; }
Examples
$y = load($x); // null, no notice
// this attitude is both readable and comfortable
if($login=POST("login") and $pass=POST("pass")) { // really =, not ==
// executes only if both login and pass were in POST
// stored in $login and $pass variables
$authorized = $login=="root" && md5($pass)=="f65b2a087755c68586568531ad8288b4";
}
Make a function which returns false if not set, and, if specified, false if empty. If valid it returns the variable. You can add more options as seen in the code below:
<?php
function isset_globals($method, $name, $option = "") {
if (isset($method[$name])) { // Check if such a variable
if ($option === "empty" && empty($method[$name])) { return false; } // Check if empty
if ($option === "stringLength" && strlen($method[$name])) { return strlen($method[$name]); } // Check length of string -- used when checking length of textareas
return ($method[$name]);
} else { return false; }
}
if (!isset_globals("$_post", "input_name", "empty")) {
echo "invalid";
} else {
/* You are safe to access the variable without worrying about errors! */
echo "you uploaded: " . $_POST["input_name"];
}
?>
Software does not magically run by the grace of god. If you are expecting something that is missing, you need to properly handle it.
If you ignore it, you are probably creating security holes in your applications. In static languages accessing a non-defined variable it is just not possible. It won't simply compile or crash your application if it's null.
Furthermore, it makes your application unmaintainable, and you are going to go mad when unexpected things happen. Language strictness is a must and PHP, by design, is wrong in so many aspects. It will make you a bad programmer if you are not aware.
I'm not sure what your definition of readability is, but proper use of empty(), isset() and try/throw/catch blocks, is pretty important to the whole process.
If your E_NOTICE is coming from $_GET or $_POST, then they should be checked against empty() right along with all the other security checks that that data should have to pass.
If it's coming from external feeds or libraries, it should be wrapped in try/catch.
If it's coming from the database, $db_num_rows() or its equivalent should be checked.
If it's coming from internal variables, they should be properly initialized. Often, these types of notices come from assigning a new variable to the return of a function that returns FALSE on a failure. Those should be wrapped in a test that, in the event of a failure, can either assign the variable an acceptable default value that the code can handle, or throwing an exception that the code can handle.
These things make the code longer, add extra blocks, and add extra tests, but I disagree with you in that I think they most definitely add extra value.
What about using the # operator?
For example:
if(#$foo) { /* Do something */ }
You may say this is bad because you have no control of what happens "inside" $foo (if it was a function call that contains a PHP error for example), but if you only use this technique for variables, this is equivalent to:
if(isset($foo) && $foo) { /* ... */ }

What is the best way to know is $_GET['example']=="somevalue"?

if((isset($_GET[example]))&&($_GET['example']=='somevalue')){ ... }
OR
if((!empty($_GET[example]))&&($_GET['example']=='somevalue')){ ... }
OR just
if($_GET['example']=='somevalue'){ ... }
I am asking that why I have seen many example where people check first if $_GET['example'] is set and then if $_GET['example']=='somevalue' ( first and second example above ).
I don't understand why not just use the last solution ( if $_GET['example']=='somevalue' then $_GET['example'] is obviously set ).
This question refers to any other variable ( $_POST, $_SERVER, ecc ).
if((isset($_GET[example]))&&($_GET['example']=='somevalue')){ ... }
Is the right one, you want to know that the "variable" exists (or is set) in order to use it. Empty just checks wether it has data of any kind or not.
For example:
<?php
$foo= 0;
if (empty($foo)) { // True because $foo is empty
echo '$foo is either 0, empty, or not set at all';
}
if (isset($foo)) { // True because $foo is set
echo '$foo is set even though it is empty';
}
if (isset($var)) { // FALSE because $var was not declared before
...
}
?>
The differences between isset and empty are subtle but important. They are most relevant when used alone. If you are checking that a variable exists and is a truethy value (e.g. any string that is not all spaces or 0s) you can use either interchangeably.
When to use isset
Use isset when it's important to know if the variable has been defined and is not null:
if (isset($maybeExistsMaybeNull)) {
// variable defined and is not NULL
}
When to use !empty
Use !empty when it's important to know if the variable has be defined and is truthy
if (!empty($mightBeEmpty)) {
// variable defined, and isn't "", " ", 0, "0" etc.
}
!empty is a great shorthand for exists and is something.
When to use array_key_exists
Use array_key_exists when it's important to know if the key exists and the value is of no importance:
if (array_key_exists('something', $array)) {
// $array['something'] exists, could be literally anything including null
}
When not to use isset
If your code looks like this:
if (isset($something) && $something) {
// code is shorter with !empty
}
When not to use !empty
If your code looks like this:
if (!empty($something) && $something === "") {
// you meant isset. this is unreachable.
}
Then you're writing code that can't be executed
Code that throws errors is error prone
Avoid writing code that issues notices/warnings that you are ignoring. For example in the question:
if((isset($_GET[example]))&&($_GET['example']=='somevalue')){ ... }
The first use of example is an undeclared constant. Or is it undeclared - what if you've got define('example', "foo"); somewhere else in the code.
if($_GET['example']=='somevalue'){ ... }
If the url doesn't contain ?example=.. that's going to issue a notice too.
Writing code without displaying errors means you can very easily miss mistakes like the first.
In context: isset and !empty are equivalent
For the example given, these two language constructs act exactly the same.
There is no case where one will act differently than the other, neither will issue a notice if the variable is undefined, and no measurable difference in performance between the two.
As others have said for checking things like $_GET and $_POST you would ideally want to use:
if ( isset($_GET['example']) && $_GET['example'] =='somevalue' ) {
// process data
}
So you always want to firstly make sure that the variable has been set (and not set to null) or in other words exists. Then proceed to check if the variable contains the data that you were expecting. If you try to make reference to a variable which doesn't exist (by not checking isset()) php will give you a notice saying 'undefined variable...etc etc'.
If you wanted to find out if a variable is set but are not concerned too much by what then you could use:
if ( !empty($_GET['example']) ) {
// process data
}
But I would be careful about using empty() on strings in this regard as empty can behave strangely with string data like '0' or ' '.
So I would always do the first one, to a) make sure the variable exists and b) is what you were expecting it to be.
This is something that you'll probably do a lot of and it helps to put together a class/functions which handles this checking for you so you dont have to do it everytime.
function checkValue($key, $value) {
if(array_key_exists($key, $_REQUEST)){
if ($_REQUEST[$key] == $value) {
return true;
} else {
return false;
}
} else {
return false;
}
}
I just use Request as a default instead of switching out (though it is preferable to switch in some cases between POST and GET for security (imo)).
Now you can just call this function anywhere
if (checkValue('Item', 'Tom') === true){} etc
the best is
if((isset($_GET[example]))&&('somevalue'==$_GET['example'])){ ... }
The difference between
'somevalue'==$_GET['example']
AND
$_GET['example']=='somevalue'
If you mistype the == and type = instead, the first notaion will raise an error to notify you.
if((isset($_GET[example]))&&($_GET['example']=='somevalue')){ ... }

Why doesn't my code to test an email address against a specific domain work?

I wanted to allow only specific email domain. Actually I did it. What i wanted to ask why my first code did not work at all.
I am just trying to learn PHP so that the question may seem silly, sorry for that.
Here is my code:
function check_email_address($email) {
$checkmail = print_r (explode("#",$email));
$container = $checkmail[1];
if(strcmp($container, "gmail.com")) {
return true;
}else {
return false;
}
}
Check out the documentation for strcmp() , it will return 0 of the two strings are the same, so that's the check you want to be doing. Also, you're using print_r() when you shouldn't be, as mentioned by the other answerers.
Anyway, here's how I would have done the function - it's much simpler and uses only one line of code:
function check_email_address($email) {
return (strtolower(strstr($email, '#')) == 'gmail.com');
}
It uses the strstr() function and the strtolower() function to get the domain name and change it to lower case, and then it checks if it is gmail.com or not. It then returns the result of that comparison.
It's because you're using print_r. It doesn't do what you seem to expect from it at all. Remove it:
$checkmail = explode("#", $email);
You can find the docs about print_r here:
http://php.net/print_r
Besides that, you can just use the following (it's much shorter):
$parts = explode("#", $email);
return (strcmp($parts[1], "gmail.com") == 0);
The following row doesn't work as you think it does:
$checkmail = print_r (explode("#",$email));
This means that you're trying to assign the return value from print_r() into $checkmail, but it doesn't actually return anything (if you don't supply the second, optional parameter with the value true).
Even then, it would've gotten a string containing the array structure, and your $container would have taken the value r, as it's the second letter in Array.
Bottom line: if your row would've been without the call to print_r(), it would've been working as planned (as long as you made sure to compare the strcmp() versus 0, as it means that the strings are identical).
Edit:
Interesting enough, I just realized that this could be achieved with the use of substr() too:
<?php
//Did we find #gmail.com at the end?
if( strtolower(substr($email, -10)) == '#gmail.com' ) {
//Do something since it's an gmail.com-address
} else {
//Error handling here
}
?>
You want:
if(strcmp($container, "gmail.com")==0)
instead of
if(strcmp($container, "gmail.com"))
Oh! And no inlined print_r() of course.
Even better:
return strcmp($container, "gmail.com")==0;
No need for the print_r; explode returns a list. And in terms of style (at least, my style) no need to assign the Nth element of that list to another variable unless you intend to use it a lot elsewhere. Thus,
$c = explode('#',$mail);
if(strcmp($c[1],'gmail.com') == 0) return true;
return false;

How to avoid isset() and empty()

I have several older applications that throw a lot of "xyz is undefined" and "undefined offset" messages when running on the E_NOTICE error level, because the existence of variables is not explicitly checked using isset() and consorts.
I am considering working through them to make them E_NOTICE compatible, as notices about missing variables or offsets can be lifesavers, there may be some minor performance improvements to be gained, and it's overall the cleaner way.
However, I don't like what inflicting hundreds of isset() empty() and array_key_exists() s does to my code. It gets bloated, becomes less readable, without gaining anything in terms of value or meaning.
How can I structure my code without an excess of variable checks, while also being E_NOTICE compatible?
For those interested, I have expanded this topic into a small article, which provides the below information in a somewhat better structured form: The Definitive Guide To PHP's isset And empty
IMHO you should think about not just making the app "E_NOTICE compatible", but restructuring the whole thing. Having hundreds of points in your code that regularly try to use non-existent variables sounds like a rather badly structured program. Trying to access non-existent variables should never ever happen, other languages balk at this at compile time. The fact that PHP allows you to do it doesn't mean you should.
These warnings are there to help you, not to annoy you. If you get a warning "You're trying to work with something that doesn't exist!", your reaction should be "Oops, my bad, let me fix that ASAP." How else are you going to tell the difference between "variables that work just fine undefined" and honestly wrong code that may lead to serious errors? This is also the reason why you always, always, develop with error reporting turned to 11 and keep plugging away at your code until not a single NOTICE is issued. Turning error reporting off is for production environments only, to avoid information leakage and provide a better user experience even in the face of buggy code.
To elaborate:
You will always need isset or empty somewhere in your code, the only way to reduce their occurrence is to initialize your variables properly. Depending on the situation there are different ways to do that:
Function arguments:
function foo ($bar, $baz = null) { ... }
There's no need to check whether $bar or $baz are set inside the function because you just set them, all you need to worry about is if their value evaluates to true or false (or whatever else).
Regular variables anywhere:
$foo = null;
$bar = $baz = 'default value';
Initialize your variables at the top of a block of code in which you're going to use them. This solves the !isset problem, ensures that your variables always have a known default value, gives the reader an idea of what the following code will work on and thereby also serves as a sort of self-documentation.
Arrays:
$defaults = array('foo' => false, 'bar' => true, 'baz' => 'default value');
$values = array_merge($defaults, $incoming_array);
The same thing as above, you're initializing the array with default values and overwrite them with actual values.
In the remaining cases, let's say a template where you're outputting values that may or may not be set by a controller, you'll just have to check:
<table>
<?php if (!empty($foo) && is_array($foo)) : ?>
<?php foreach ($foo as $bar) : ?>
<tr>...</tr>
<?php endforeach; ?>
<?php else : ?>
<tr><td>No Foo!</td></tr>
<?php endif; ?>
</table>
If you find yourself regularly using array_key_exists, you should evaluate what you're using it for. The only time it makes a difference is here:
$array = array('key' => null);
isset($array['key']); // false
array_key_exists('key', $array); // true
As stated above though, if you're properly initializing your variables, you don't need to check if the key exists or not, because you know it does. If you're getting the array from an external source, the value will most likely not be null but '', 0, '0', false or something like it, i.e. a value you can evaluate with isset or empty, depending on your intent. If you regularly set an array key to null and want it to mean anything but false, i.e. if in the above example the differing results of isset and array_key_exists make a difference to your program logic, you should ask yourself why. The mere existence of a variable shouldn't be important, only its value should be of consequence. If the key is a true/false flag, then use true or false, not null. The only exception to this would be 3rd party libraries that want null to mean something, but since null is so hard to detect in PHP I have yet to find any library that does this.
Just write a function for that. Something like:
function get_string($array, $index, $default = null) {
if (isset($array[$index]) && strlen($value = trim($array[$index])) > 0) {
return get_magic_quotes_gpc() ? stripslashes($value) : $value;
} else {
return $default;
}
}
which you can use as
$username = get_string($_POST, 'username');
Do the same for trivial stuff like get_number(), get_boolean(), get_array() and so on.
I believe one of the best ways of coping with this problem is by accessing values of GET and POST (COOKIE, SESSION, etc.) arrays through a class.
Create a class for each of those arrays and declare __get and __set methods (overloading). __get accepts one argument which will be the name of a value. This method should check this value in the corresponding global array, either using isset() or empty() and return the value if it exists or null (or some other default value) otherwise.
After that you can confidently access array values in this manner: $POST->username and do any validation if needed without using any isset()s or empty()s. If username does not exist in the corresponding global array then null will be returned, so no warnings or notices will be generated.
I don't mind using the array_key_exists() function. In fact, I prefer using this specific function rather than relying on hack functions which may change their behavior in the future like empty and isset (strikedthrough to avoid susceptibilities).
I do however, use a simple function that comes handy in this, and some other situations in dealing with array indexes:
function Value($array, $key, $default = false)
{
if (is_array($array) === true)
{
settype($key, 'array');
foreach ($key as $value)
{
if (array_key_exists($value, $array) === false)
{
return $default;
}
$array = $array[$value];
}
return $array;
}
return $default;
}
Let's say you've the following arrays:
$arr1 = array
(
'xyz' => 'value'
);
$arr2 = array
(
'x' => array
(
'y' => array
(
'z' => 'value',
),
),
);
How do you get the "value" out of the arrays? Simple:
Value($arr1, 'xyz', 'returns this if the index does not exist');
Value($arr2, array('x', 'y', 'z'), 'returns this if the index does not exist');
We already have uni and multi-dimensional arrays covered, what else can we possibly do?
Take the following piece of code for instance:
$url = 'https://stackoverflow.com/questions/1960509';
$domain = parse_url($url);
if (is_array($domain) === true)
{
if (array_key_exists('host', $domain) === true)
{
$domain = $domain['host'];
}
else
{
$domain = 'N/A';
}
}
else
{
$domain = 'N/A';
}
Pretty boring isn't it? Here is another approach using the Value() function:
$url = 'https://stackoverflow.com/questions/1960509';
$domain = Value(parse_url($url), 'host', 'N/A');
As an additional example, take the RealIP() function for a test:
$ip = Value($_SERVER, 'HTTP_CLIENT_IP', Value($_SERVER, 'HTTP_X_FORWARDED_FOR', Value($_SERVER, 'REMOTE_ADDR')));
Neat, huh? ;)
Welcome to null coalescing operator (PHP >= 7.0.1):
$field = $_GET['field'] ?? null;
PHP says:
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.
I'm here with you. But PHP designers has made a lot more worse mistakes than that. Short of defining a custom function for any value reading, there isn't any way around it.
I use these functions
function load(&$var) { return isset($var) ? $var : null; }
function POST($var) { return isset($_POST[$var]) ? $_POST[$var] : null; }
Examples
$y = load($x); // null, no notice
// this attitude is both readable and comfortable
if($login=POST("login") and $pass=POST("pass")) { // really =, not ==
// executes only if both login and pass were in POST
// stored in $login and $pass variables
$authorized = $login=="root" && md5($pass)=="f65b2a087755c68586568531ad8288b4";
}
Make a function which returns false if not set, and, if specified, false if empty. If valid it returns the variable. You can add more options as seen in the code below:
<?php
function isset_globals($method, $name, $option = "") {
if (isset($method[$name])) { // Check if such a variable
if ($option === "empty" && empty($method[$name])) { return false; } // Check if empty
if ($option === "stringLength" && strlen($method[$name])) { return strlen($method[$name]); } // Check length of string -- used when checking length of textareas
return ($method[$name]);
} else { return false; }
}
if (!isset_globals("$_post", "input_name", "empty")) {
echo "invalid";
} else {
/* You are safe to access the variable without worrying about errors! */
echo "you uploaded: " . $_POST["input_name"];
}
?>
Software does not magically run by the grace of god. If you are expecting something that is missing, you need to properly handle it.
If you ignore it, you are probably creating security holes in your applications. In static languages accessing a non-defined variable it is just not possible. It won't simply compile or crash your application if it's null.
Furthermore, it makes your application unmaintainable, and you are going to go mad when unexpected things happen. Language strictness is a must and PHP, by design, is wrong in so many aspects. It will make you a bad programmer if you are not aware.
I'm not sure what your definition of readability is, but proper use of empty(), isset() and try/throw/catch blocks, is pretty important to the whole process.
If your E_NOTICE is coming from $_GET or $_POST, then they should be checked against empty() right along with all the other security checks that that data should have to pass.
If it's coming from external feeds or libraries, it should be wrapped in try/catch.
If it's coming from the database, $db_num_rows() or its equivalent should be checked.
If it's coming from internal variables, they should be properly initialized. Often, these types of notices come from assigning a new variable to the return of a function that returns FALSE on a failure. Those should be wrapped in a test that, in the event of a failure, can either assign the variable an acceptable default value that the code can handle, or throwing an exception that the code can handle.
These things make the code longer, add extra blocks, and add extra tests, but I disagree with you in that I think they most definitely add extra value.
What about using the # operator?
For example:
if(#$foo) { /* Do something */ }
You may say this is bad because you have no control of what happens "inside" $foo (if it was a function call that contains a PHP error for example), but if you only use this technique for variables, this is equivalent to:
if(isset($foo) && $foo) { /* ... */ }

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