That’s exactly the point. The zero value is the failure.
The zero value is the failure.
No, the failure is that you dont know it failed and send a bad query to the database.
Are you saying it is better for bad data to pass through the app, and make bad query calls to the DB putting unnecessary load on it instead of catching it first?
Consider an app with as many users as facebook or twitter. Would it be a good idea to allow millions of bad calls to the DB and put that load on it? It would be an extreme unnecessary load on the DB simply because you didn’t catch the bad data before making the DB call.
What part of my code does not detect the failure?
[php]
$id = (int) $_GET[‘ID’];
if (!$id) {
// not valid
}
[/php]
Typecasting is one of the most important things you can do. If you aren’t doing it, you’re doing it wrong.
For an ID? really? Lets go with your code. To be clear, we are only talking about a record ID that is most usually a number ONLY.
Now lets go with your code:
[php]<?php
$_GET[‘ID’]="-8-10-5-6";// VALID INTEGER
$id = (int) $_GET[‘ID’];
if (!$id) {
echo “Not Valid”;
}
else
{
echo “Valid”;// yayyy! -8-10-5-6 is valid integer.
// I get to sneak by and make a bogus call the database and ask for ID -8
}
?>[/php]
“-8-10-5-6” is a valid integer, so according to your way, we make a bad call to the database for a record with a value of -8.
So , making bad calls to the database instead of catching and handling the error is the right way to do it according to you?
Now, lets go with the code I gave as an example.
[php]if(!preg_match("/^[0-9]+$/", $_GET[‘ID’])) {
echo “NOT Valid $id”;// Uh oh! -8 is not a valid ID we want to allow.
//We never even get to think about making a query to the database and now we can decide how to handle this error.
}
else {
echo “Valid $id”;
}[/php]
-8 will never get past the validation check and the database will not get hit with a bogus query.
So, do still say I am doing it wrong? This is not even about our personal coding opinions. The code speaks for itself.
Summary:
If I use your code, bogus query’s could be sent to my database potentially in the millions. I dont get to trap and handle the error.
If I use the code I posted, the query is NEVER sent to the DB and the database isn’t aware that anything has happened. I DO get to trap and handle the error.
I’ll throw my hat into the ring…
[php]
if (is_numeric($id) && ($id >= 0)) {
//db function call
} else {
Echo “{$id} is not valid.”;
}[/php]
If anything if fundamentally wrong with it let me know, but unless you enjoy regex it removes the need.
unless you enjoy regex it removes the needNot so, it is actually worse.
Per the docs:
Finds whether the given variable is numeric. Numeric strings consist of optional sign, any number of digits, optional decimal part and optional exponential part. Thus +0123.45e6 is a valid numeric value. Hexadecimal (e.g. 0xf4c3b00c), Binary (e.g. 0b10100111001), Octal (e.g. 0777) notation is allowed too but only without sign, decimal and exponential part.
All of these return true for is_numeric. Do these look like values you would want to pass to the DB as an ID?
[php] 0x539,
02471,
0b10100111001,
1337e0,
9.1,
+0123.45e6,
0xf4c3b00c,
0b10100111001[/php]
is_numeric allows even more non-numeral characters. I was going to mention about is_numeric, but I wanted to see if anyone would suggest it.
- As I think about it, PHP should invent a function called is_numeral that only allows whole numbers (0-9)
You’re not making any sense here. Yes, -8 is a valid integer.
So is 929392923293293239. The same would be a “bad call to the database” in your eyes.
If you think evaluating a string as an integer is the way to go, by all means go for it.
Even the laravel source code (which I have great respect for) shows is_numeric being used for validation. If you think you can avoid injection of invalid values to your database, you are wrong. All you can do is ensure they are not harmful to you.
The whole point is, if your expecting a number ONLY, check for a number ONLY.
THIS:
[php]<?php
$_GET[‘ID’]=‘clearlyAstring’;
$var=(preg_match("/^[0-9]+$/", $_GET[‘ID’]));
var_dump($var);
?>[/php]
EVALUATES TO EXACTLY THE SAME THING AS THIS:
[php]<?php
var_dump((int)$_GET[‘ID’]=‘clearlyAstring’);
?>[/php]
So your point quoted above is meaningless.
The biggest difference is the first example will allow ONLY numbers to get past which is exactly what an ID should be normally be.
So is 929392923293293239. The same would be a "bad call to the database" in your eyes.If it does not exist as an ID then of course it is a "bad call", meaning a useless hit to the database. A useless database hit has nothing to do with "My eyes". It is just useless period. You could easily limit the max number you want to accept as an ID at this point.
With the preg function you have at least eliminated EVERYTHING that is not numbers ONLY which is what you are expecting.
After a bit of research and testing it turns out that Strider provided the best answer for checking for a numeral only using FILTER_VALIDATE_INT that satisfies all the points I made about is_numeric, is_integer, preg_match, and (int) as well as the points M@tt made. See the code test below.
Cheers Strider
[php]<?php
$options = array(
‘options’ => array(
‘min_range’ => 1,
‘max_range’ => 5000000000
)
);
$var = filter_var(‘25’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //Valid AND is integer
echo “
$var = filter_var(‘0’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //FAIL
echo “
$var = filter_var(‘clearlyAstring’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //FAIL
echo “
$var = filter_var(’-8’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //FAIL
echo “
$var = filter_var(‘0x539’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //FAIL
echo “
$var = filter_var(‘02471’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //FAIL
echo “
$var = filter_var(‘0b10100111001’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //FAIL
echo “
$var = filter_var(‘1337e0’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //FAIL
echo “
$var = filter_var(‘9.1’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //FAIL
echo “
$var = filter_var(’+0123.45e6’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //FAIL
echo “
$var = filter_var(‘0xf4c3b00c’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //FAIL
echo “
$var = filter_var(‘0b10100111001’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //FAIL
echo “
$var = filter_var(‘929392923293293239’, FILTER_VALIDATE_INT, $options);
echo “
”;”;
var_dump($var); //FAIL - M@tt example - All numerals but exceeds max_range
echo “
?>[/php]