if(empty) validation fires when trying to select 0 from select list

Black Sulfur
Black Sulfur used Ask the Experts™
on
I have a simple select list and just want to make sure that if nothing is selected and it is left on it's default of "Please select", then an error message will display. This works fine but when I select zero then the error still fires. 0 should be an acceptable option.

 
<select class="form-control" name="actual">
	<option value="">Please select</option>
	<option value="0">0</option>
	<option value="1">1</option>
	<option value="2">2</option>
	<option value="3">3</option>
	<option value="4">4</option>
	<option value="5">5</option>
	<option value="6">6</option>
	<option value="7">7</option>
	<option value="8">8</option>
	<option value="9">9</option>
	<option value="10">10</option>
	<option value="11">11</option>
	<option value="12">12</option>
	<option value="13">13</option>
	<option value="14">14</option>
	<option value="15">15</option>
</select>

Open in new window


		if(empty($_POST['actual'])) {
			
			$message .= "Please enter your target <br/>";
		}

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Commented:
PHP manual (http://php.net/EMPTY) states:
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)

You can use something like
<option value="zero">0</option>

Open in new window

or use !isset() instead of empty()

Author

Commented:
I have set the column in the database as an integer. So, will this:

<option value="zero">0</option>

Open in new window


enter a "0" in the database?

Author

Commented:
(!isset($_POST

Open in new window


did not work..
OWASP: Avoiding Hacker Tricks

Learn to build secure applications from the mindset of the hacker and avoid being exploited.

Commented:
No, you need an additional translation like this:
if ($my_variable == "zero"){
              $my_variable=0;
              }

Open in new window

Author

Commented:
Hmm. That seems like a long way around. I have an idea. What do you think about this?

if(strlen($_POST['actual']) < 1) {

Open in new window

Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
<?php
$actual = isset($_POST['actual']) ? $_POST['actual'] : '';
if ($actual != '') {
   echo "Good";
}
else {
	echo "Bad";
}?>

<form method="post">

<select class="form-control" name="actual">
	<option value="">Please select</option>
	<option value="0">0</option>
	<option value="1">1</option>
	<option value="2">2</option>
	<option value="3">3</option>
	<option value="4">4</option>
	<option value="5">5</option>
	<option value="6">6</option>
	<option value="7">7</option>
	<option value="8">8</option>
	<option value="9">9</option>
	<option value="10">10</option>
	<option value="11">11</option>
	<option value="12">12</option>
	<option value="13">13</option>
	<option value="14">14</option>
	<option value="15">15</option>
</select>

<input type="submit" />
</form>

Open in new window

Working sample here
Most Valuable Expert 2011
Top Expert 2016

Commented:
So, will this:

<option value="zero">0</option>

enter a "0" in the database?
Not by itself, but it will put the word "zero" into the request variables if it is the selected option.
Dave BaldwinFixer of Problems
Most Valuable Expert 2014

Commented:
I never use 'empty' (don't remember why) but I do use a POST filter and I usually use '-' as the default value for 'select statements.  'isset' won't consider any of those values to be Not Set.  This is an example of what I normally use:
if (!isset($_POST['name']))  $name = ''; else $name = $_POST['name'];

Open in new window

Most Valuable Expert 2011
Top Expert 2016

Commented:
@Dave: New syntax (sugar only) for PHP 7.  "Null coalescing operator" simplifies a common task and it's chainable -- the first isset() value will be used to assign the variable.
https://wiki.php.net/rfc/isset_ternary
http://php.net/manual/en/migration70.new-features.php
$name = $_POST['name'] ?? '';

Open in new window

Note that empty() is loosely typed, but isset() has no understanding of type.  A value of zero ('0') is TRUE for empty().
Dave BaldwinFixer of Problems
Most Valuable Expert 2014
Commented:
What???  Learn something New???  I'm lucky that I've been able to get my customers up to PHP 5.4 and 5.5.  And that was only because Paypal and others won't work with PHP 5.3 and below.  And since I'm using 'isset' on POST and GET values, it only has to 'understand' text because that's all you get with those.

I have hundreds, maybe thousands of lines like my example.  Although on newer ones I also limit the size with a substr() statement.
if (!isset($_POST["appEmail"])) $appEmail = ''; else $appEmail = substr($_POST["appEmail"],0,64);

Open in new window

Most Valuable Expert 2011
Top Expert 2016
Commented:
Here's an example suitable to the Author's question.  Remove comment markers on line 27 before flight with PHP7 :-)
https://iconoun.com/demo/temp_black_sulfur.php
<?php // demo/black_sulfur.php
/**
 * https://www.experts-exchange.com/questions/29010971/if-empty-validation-fires-when-trying-to-select-0-from-select-list.html
 *
 * http://php.net/manual/en/migration70.new-features.php
 */
error_reporting(E_ALL);


if (!empty($_POST))
{
    // PHP < 7
    if (isset($_POST['actual']))
    {
        if ($_POST['actual'] == 'choose')
        {
            $actual = 'NOTHING';
        }
        else
        {
            $actual = $_POST['actual'];
        }
    }


    // PHP 7+ IS MUCH SIMPLER SYTAX
    // $actual = $_POST['actual'] ?? 'NOTHING';

    echo PHP_EOL . "YOU CHOSE $actual";

}


$form = <<<EOD
<form method="post">
<select class="form-control" name="actual">
	<option value="choose">Please select</option>
	<option value="0">0</option>
	<option value="1">1</option>
	<option value="2">2</option>
</select>
<input type="submit" name="submit" />
</form>
EOD;

echo $form;

Open in new window

The value zero or the string zero is kind of a unique case for PHP.  Every PHP programmer who ever achieves anything of value memorizes these pages:
http://php.net/manual/en/types.comparisons.php
http://php.net/manual/en/language.types.type-juggling.php
http://php.net/manual/en/language.types.string.php#language.types.string.conversion
Most Valuable Expert 2017
Distinguished Expert 2018
Commented:
Not sure why this has become so complicated - the solution is simple. If the POST value exists set your variable to it otherwise set the variable to the SAME value as the default option in the <select> - then all you have to do is check for the default value in the select.
From OP
<select class="form-control" name="actual">
	<option value="">Please select</option>

Open in new window

// PHP 7+ IS MUCH SIMPLER SYTAX
$actual = $_POST['actual'] ?? '';

Open in new window

//PHP < 7
$actual = isset($_POST['actual']) ? $_POST['actual'] : '';

Open in new window

Then do the test for the default value
if ($actual !== '') {
}

Open in new window

Dave BaldwinFixer of Problems
Most Valuable Expert 2014

Commented:
Please note that all PHP pages that receive form values, either GET or POST, can expect spam, sometimes a lot of automated spam.  Last month a spammer found a form that I had not protected properly and POSTed 754 times to it before the hosting company blocked them.  My customer wasn't happy with receiving 754 spam emails.  They were all intended to cause SQL injection.  They didn't, I wasn't that dumb.

Normally on these pages I check the referrer which works almost all of the time because spammers are lazy.  I had forgotten to do that on that page.  Using substr() to limit the size of the data helps too.
Most Valuable Expert 2011
Top Expert 2016

Commented:
@Julian: for you, Dave, me, this is not complicated, and there are lots of ways to get to a good solution.  But if you're new to PHP you might not know that zero, whether expressed as an integer 0 or as a string '0', is one of the values that evaluates boolean TRUE for empty().  And sometimes (perish the thought) a new PHP programmer might copy some code without looking up the function reference descriptions on PHP.net.  So the new-to-PHP programmer might not come across the explanation of the multi-layered meaning of PHP empty().  And there might be some assumptions that are wrong or incomplete.

When I'm in the classroom, I call this sort of understanding the "apple pie problem."  You have seen an apple pie, and you smelled it and tasted it.  And you love it!  Then your friend brings you a bushel of apples and says, "Let's make an apple pie."  You would love to make an apple pie -- one that smelled and tasted wonderful, but you can't because you're ignorant of the processes and additional ingredients that you need to make the pie, and you don't even know that you're missing the important information.  

Your first try might be to put all the apples into the oven and see what you get.  This is sort of like copying code without understanding the code.  The outcome is not usually good.  Burnt apples, wasted time, brown sadness mess, tears.

So you pick yourself up.  To fill in the missing information you turn to a recipe.  And that recipe calls for a crust, so you need another recipe.  It becomes a major knowledge-building moment.  For those new to PHP, a basic part of that knowledge-building moment is reading the function reference page for every function that is new or even slightly unfamiliar.  Never copy code you don't understand!

I could not work without a browser window open to the PHP.net function reference.  There is just too much to memorize in a language with 1,500+ functions.  So I use and recommend the online man pages.
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
I meant the solutions being offered. The principle that needs to be conveyed in addition to the falsy / truthy is that the core of the problem here is more to do with how to distinguish between a default value and non-existence.

For the purposes of the required outcome these two are the same - all that is needed is some way to elegantly determine which.

The solution is to check for existence and default the value to the <select> default if the POST variable does not exist. I think we have covered in detail the issues of 0,'',false and null.

The point I was trying to make was based on the author deviating from his original post to start using values like "zero" - my intent was to illustrate that his original approach was mostly there all he needed to was add the line for the extraction of the POST and modify the line to test this value for the default.
Dave BaldwinFixer of Problems
Most Valuable Expert 2014

Commented:
So if you want '0' to be an acceptable value, you can't use 'empty()'.  You can use 'isset()' as I have shown because all GET and POST values are received as text.  They are easily and often automatically converted into numbers by both PHP and MySQL.

Author

Commented:
Wow, talk about getting more than I bargained for. I did not expect this much feedback, so thanks to all who assisted!

EE, are you listening? I am AGAIN in the situation where I just want to give everyone the same level of acceptance/best answer because everyone made a valuable contribution and I now have to pick a "best" answer.

I'll have to have a few pints after work and then just click wherever my finger takes me :-P
Most Valuable Expert 2011
Top Expert 2016

Commented:
Further to Dave's point about ..."all GET and POST values are received as text."  Except for radio buttons and check boxes, which might or might not be received at all.  There is no end to all of the rabbit holes that PHP has created for us!
greetings black sulfer,  I have used the test for strlen($_POST['input']) to good effect, At first I thought it would throug a "warning" if the $_POST['input']) was not defined (not set), but it did not, it returns 0.

you may try -
if(!strlen($_POST['actual']) ){
  $message .= "Please enter your target <br/>";
  }

if you only need to detect a not set or an empty string, ,
but please consider better filtering as  Dave Baldwin suggested, the spammers are alive, creative and persistent?

Author

Commented:
Thanks Slick812. I would hope that spammers won't be an issue because this is all happening within a password protected area. But I don't want to assume anything....
Most Valuable Expert 2011
Top Expert 2016

Commented:
PHP strlen() will throw a Notice, not a Warning, if the variable or array index is not set.  If error_reporting(E_ALL) is on, you will see the Notice.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial