可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm working on a database driven site which is using normal database methods rather than prepared statements. Because of this I have to sanitise POST and GET variables when passed to a form action PHP script.
There is a sanitise
method defined which attempts to sanitise the user input as best as possible but I am trying to cut down the code that tests for the POST and GET variable's existence and the code for defining variables with default values if they don't exist.
This is what I came up with but its leaving a bad taste in mine and other dev's mouth as we all feel that the error suppression operator is being abused:
$Page = sanitise(@$_GET["page"], "Unspecified");
$Timestamp = sanitise(@$_POST["time"], time());
Please can you give me some critique of this code? It's not ideal I'll agree, but it does cut down on a lot of code and is a lot more readable than what we had.
I tried to achieve the following in one line:
- Test for a variable's existence.
- If it exists, sanitize the input and assign to a variable.
- If it doesn't exist, create a variable but use a default value.
What do you think?
This is sort of a continuation of what I was asking here:
Passing unset variables to functions
回答1:
Save yourself some coding and make an "Input" class with several static functions, like this:
class Input {
public static function get($key, $default = null)
{
return (array_key_exists($key, $_GET)) ? $_GET[$key] : $default;
}
// same thing for $_POST...
}
Then you could call your sanitize function like so...
sanitize(Input::get('page', 'Unspecified'));
回答2:
Using the @
operator is, indeed, generally considered as bad practice.
In your case, it could be avoided, by splitting things in several steps :
- testing the variable is set -- with
isset()
- working on it -- or not :
- if set, sanitizing it
- else, using a default value.
As the @
operator can be avoided, here... well, I would avoid it.
Notes :
- masking errors is generally not such a good idea (in this case, it shouldn't hurt much... but, still)
- and the
@
operator has a cost, speaking of performances1.
- one-liners is not a goal one should necessarily have ;-)
1. But some will say it doesn't matter that much -- and they are probably right
回答3:
You could use the terany operator to test for existence, avoiding using the error suprression operator:
$Page = (!empty($_POST['test'])) ? $_POST['test'] : 'default';
Generally using the suppression operator is viewed as a bad practice, so using the terany operator like this would avoid suppressing errors as well as give you the desired effect.
回答4:
The @ operator do not avoid the error, it makes it quite. But if you check for error you will have one. This is why it's a bad practice. But also because hiding errors generally brings troubles.
A good way is this:
$Page = (isset($_GET['page'])) ? $_GET['page'] : 'default';
$Page = sanitise($Page, "Unspecified");
But since you have a sanitise() function, you could upgrade it and make it this check for you.
function sanitise($value, $default, $fromRequest=false) {
if ($fromRequest) $value = (isset($_REQUEST[$value])) ? $_REQUEST$value] : $default;
..
}
$_REQUEST is the global variable that represents $_GET + $_POST + $_COOKIE, but you may cutomize my version.
回答5:
In general, the other answers are correct. There are issues using @
to just pretend that errors don't exist.
That said, in this case, I'd use your approach. It's legible, concise and — in this small scenario — just does the job. I'm hard-pressed to think of potential bugs here.
回答6:
To avoid the cargo cult programming syntax with isset
I'm using object wrappers around the input arrays. It specifically does the checking behind the scenes, so I can avoid both the silly isset and @.
For your example I would write $_GET->int->default("time", time())
or $_GET->sanitize["page"]
and if all rules are predefined just $_GET["whatever"]
with automatic filtering.
Otherwise I'd still be using @$_GET, because I do not believe in appearance coding.