PHP request as array? - php

Im trying to load content via request and include pages, problem is that even if I put localhost/?login or ?logout , it doesn't work, shows that there is no request with name $k and priting $container .= twice (??). I never had a problems with array but I didn't try it as a website request.
$actions = array(
"login" => "source/login.php",
"logout" => "source/logout.php"
);
foreach($actions as $k => $v){
if (!empty($_REQUEST[$k])) {
include($v);
break;
}
else
{
$container .= "?";
}
}

That your punishment for using empty. :-) Lots of values are considered empty by PHP.
Since login is just a key, but you didn't specify a value, it is considered 'empty' even though it exists in the array.
Use array_key_exists for a stricter check.
foreach($actions as $k => $v){
if (array_key_exists($k, $_REQUEST)) {
include($v);
break;
}
else
{
$container .= "?";
}
}
Many people use isset for this, which is slightly better than empty, but I prefer array_key_exists since it does exactly what you expect it to do and nothing else.
The following things are considered to be empty according to the docs:
"" (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 you can see why empty can give you a lot of false positives when testing for it. :-)

another way you could do it was have your links be setup like this:
foo.com/bar.php?action=login
then have your php code do
$action = $_REQUEST['action'];
if ($action == "" || array_key_exists($action,$actions) )
{
//set to default value...
}
include($actions[$action]);
would this achieve your goal?

Related

empty() not working in PHP

I am working with PHP 5.4 and I am submitting a form via POST request, and I want to check to see if one of the values is null, or populated. However the condition does not appear to resolving to true and I can't figure out what I'm doing wrong.
Here is the code:
$route = $_POST['route'];
echo ("route: " . $route);//this is displaying 'route:null'
if(empty($route))
{
echo ("route2: " . $route);
}
I have also tried to use isset is_null and $route === null $route == null
None seem to work .
I have also tried inserting true into the if statement to make sure that true is resolving correctly, but it does.
If the echo is displaying null then it is not null. It is a string "null" which are two entirely different things.
This, in fact is a common problem when using javascript to post to php. Javascript's null gets converted to string when posting to php, thus passing all checks (empty(), isset(), ...).
The easiest way to see these issues is to do a var_dump($_POST), which will give you exactly what you have received in your post.
In your case you are receiving string "null", which in no way can pass the empty() check. You either need to check if $route=="null" or fix your javascript so it does not send null values.
Fixing javascript is the proper way to go.
The POST variable does not contain anything. Either it does not exist on the form or you have it misspelled.
According to the docs null is empty.
http://us3.php.net/empty
Returns FALSE if var exists and has a non-empty, non-zero value.
Otherwise returns TRUE.
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)
Empty - Determine whether a variable is considered to be empty. A variable is considered empty if it does not exist or if its value equals FALSE. empty() does not generate a warning if the variable does not exist.
How about try using (or adding):
if(is_null($route))
or
if(!isset($route))
if( isset($_POST['route']) && !empty($_POST['route']) ) {
$route = $_POST['route'];
echo "Route: $route";
} else {
echo "Route: None specified";
}
Because the $_POST is returning null as a string I had to do this:
$route = $_POST['route'];
echo ("route: " . $route);
if($route == 'null')//surround null in quotes
{
echo ("route2: " . $route);
}
Try This ;)
function convert_null($data)
{
$data = str_replace(null,"",$data);
$data = str_replace("null","",$data);
$data = trim($data);
return $data;
};
convert_null($route);
if(empty($route))
{
echo ("route2: " . $route);
};

Workaround for isset, array_key_exists and !empty [duplicate]

This question already has answers here:
Why check both isset() and !empty()
(10 answers)
Closed 12 months ago.
When coding php I try to avoid as many warnings as possible. There is one question that bugs me for quite some time now, regarding arrays.
When working with arrays and their values I often check for empty values first before I go to the "real work".
if(array_key_exists('bla', $array){
if( !empty($array['bla']) {
# do something
}
}
My Question is:
This is a lot of code for just checking if I have values to work with. Is there some shorter way to check a value within an array that may or may not exist?
Don't use empty unless you are sure that's what you want:
Returns FALSE if var exists and has a non-empty, non-zero value. Otherwise returns TRUE.
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)
The manual doesn't explicitly list the "if var doesn't exist" cases, but here are a couple:
$array['undeclaredKey'] (an existing array, but key not declared)
$undeclaredVar; (a variable not declared)
Usually the array_key_exists check should suffice.
If you are checking for a non-empty value, then you can just use !empty($array['bla']).
You can also use isset($array['bla']), which returns false when: 1) key is not defined OR 2) if the value stored for the key is null. The only foolproof way to check if the array contains a key (even if its value is null) is to use array_key_exists().
The call to empty() is safe even if the key exists (behaves like isset()), so you don't have to protect it by the array_key_exists().
I am surprised this was not mentioned, but the shortest way fetch a value for a key without generating a warning/error is using the Error Control Operator:
// safely fetch from array, will return NULL when key doesn't exist
$value = #$array['bla'];
This allows you get the value for any key with the possibilty of its return value being null if the key does not exist.
You can simply do
if (!empty($array['bla']) {
# do something
}
I use that all the time in drupal and is good way to check if is available and avoid any kind of warnings.
Just do:
if (!empty($array['bla'])) {
There will be no warning if the key doesn't exist.
Not sure why no one mentioned isset yet, but you could do something like this:
// Before
if(array_key_exists('bla', $array){
if( !empty($array['bla']) {
// After (if element of array is scalar)
// Avoids warning and allows for values such as 0
if ((true === isset($array['bla'])) && (mb_strlen($array['bla']) > 0)) {
// After (if element of array is another array
// Avoids warning and ensures element is populated
if ((true === isset($array['bla'])) && (count($array['bla']) > 0)) {
If you really want to get crazy with a better way of checking vars, you could create a standardized API, below are a few methods I created to avoid laundry list function calls for variable checking:
class MyString
{
public static function populated($string)
{
//-----
// Handle various datatypes
//-----
// Don't want to assume an array as a string, even if we serialize then check
if (is_array($string)) {
return false;
}
if (is_object($string)) {
if (!is_callable(array($string, '__toString'))) {
return false;
}
$string = (string) $string;
}
//-----
return (mb_strlen($string) > 0) ? true : false;
}
}
class MyArray
{
public static function populatedKey($key, $array, $specificValue = null, $strict = true)
{
if ((is_array($array)) &&
(array_key_exists($key, $array))) {
if (is_array($array[$key])) {
return (count($array[$key]) > 0) ? true : false;
}
elseif (is_object($array[$key])) {
return true;
}
elseif (mb_strlen($array[$key]) > 0) {
if (!is_null($specificValue)) {
if ($strict === true) {
return ($array[$key] === $specificValue) ? true : false;
} else {
return ($array[$key] == $specificValue) ? true : false;
}
}
return true;
}
}
return false;
}
}
// Now you can simplify calls
if (true === MyArray::populatedKey('bla', $array)) { // Do stuff }
if (true === MyString::populated($someString)) { // Do stuff }
There are 1K ways to skin a cat, but standardizing calls like this increase Rapid Application Development (RAD) quite a bit, keeps the calling code clean, and helps with self documentation (semantically logical).

PHP - refactoring this if statement to avoid duplication

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

Catch blank (including all-whitespace) form submissions

If have a problem on my site that users can post empty messages if they use space.
Code:
if (isset($_POST['submit'])) {
// check for empty fields
if (empty($_POST['headline']) || empty($_POST['text']) ||
empty($_POST['forum_id'])) {
header("Refresh: 2; url=/add-thread");
die('You must fill out every field.');
}
// No errors? Save.
else {
$headline = mysql_real_escape_string($_POST['headline']);
$text = mysql_real_escape_string($_POST['text']);
mysql_query("INSERT INTO threads (headline, text, date, forum_id, user_id)
VALUES ('$headline', '$text', NOW(), '$_POST[forum_id]', '$user[id]')");
header("Location: /thread/".mysql_insert_id()."");
}
}
How can I fix this?
trim() the text inputs. You can do that easily like this:
// get input vars and trim space
$callback = array('filter' => FILTER_CALLBACK, 'options' => 'trim');
$fields = filter_input_array(INPUT_POST, array(
'headline' => $callback,
'text' => $callback,
'forum_id' => $callback,
));
// check for empty fields by counting how many are set
if ( count($fields) != count(array_filter($fields)) ) {
// something was unset
}
The empty function checks for variables that meet a set criteria, from the manual
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)
Your $_POST fields actually contain something like this
" ";
This isn't and empty string, but a string that's filled with whitespace characters.
Before using empty(), trim() the white-space from your POSTed values
$trimmed_post = array();
foreach($_POST as $key=>$value){
$trimmed_post[$key] = $value;
}
if(!empty($trimmed_post['headline'])){
//...
}
You don't need to put the new values into a new array, but I'm not a big fan of changing what's in the auto-generated superglobals.
One final note, you can't do something like this
if(!empty(trim($_POST['headline']))){
//...
}
because the empty function expects to be passed an actual variable. You could do something like this instead
if('' != trim($_POST['headline'])){
//...
}
This is probably the best approach to take. You reduce the number of functions that you need to call, users can post entries with a value of 0, and the code is more explicit about what it does. Another form you'll see is
if(trim($_POST['headline'])){
}
This works because PHP evaluates an empty string ('') as false, and a non empty string as true. I tend to avoid this form because I've found a lot of PHP bugs crop up around misunderstandings on how the equality operators get boolean values out of certain types. Being explicit helps reduce occurrences of these types of bugs.
Just a quick note: You're injecting the value of $_POST['forum_id'] into the SQL; that's not a good idea, since a user could manipulate that value as desired, even if it is coming from a hidden field. It would be wise to escape the value, or at least pass it through intval() and ensure it's an integer (assuming integral post identifiers).
I agree that trimming is the way to go. Here's a much easier way to go about it:
$_POST = array_map('trim', $_POST);
Try
if (!empty($_POST['headline']) && !empty($_POST['text']) &&
!empty($_POST['forum_id']))
For the logic.
You'd have to switch it around though.
UPDATE to clarify:
if (isset($_POST['submit']) && !empty($_POST['headline']) &&
!empty($_POST['text']) && !empty($_POST['forum_id'])) {
$headline = mysql_real_escape_string($_POST['headline']);
$text = mysql_real_escape_string($_POST['text']);
mysql_query("INSERT INTO threads (headline, text, date, forum_id, user_id)
VALUES ('$headline', '$text', NOW(), '$_POST[forum_id]', '$user[id]')");
header("Location: /thread/".mysql_insert_id()."");
}
else
{
header("Refresh: 2; url=/add-thread");
die('You must fill out every field.');
}
}
I trim every $_GET & $_POST variable as soon as the app starts. try something like this:
function trimArray(&$array) {
if (empty($array)) {
return;
}
foreach ($array as $k => $v) {
if (! is_array($v)) {
$array[$k] = trim($v);
} else {
trimArray($v);
}
}
}
if (! empty($_GET)) {
trimArray($_GET);
}
if (! empty($_POST)) {
trimArray($_POST);
}
Right after checking for a submission:
foreach ( $_POST as $key => &$value ) $value = trim($value);
edit in response to asker's comment:
Odd that it didn't work as above. Here was my exercise to confirm it would.
tbramble#wayfarer:~$ php -a
Interactive shell
php > $arr = array('one',' two', ' three ');
php > print_r($arr);
Array
(
[0] => one
[1] => two
[2] => three
)
php > foreach ( $arr as $key => &$value ) $value = trim($value);
php > print_r($arr);
Array
(
[0] => one
[1] => two
[2] => three
)
Must have something to do with working on a superglobal instead of a normal array.

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