Actually I'd change that slightly: 1) Filter/sanitize input (php.net/filter works great for this) 2) Sanity check input (bounds/type checking and then check if it is legit against the datasource) a) I use intval() when I expect numeric input. It will scrub out anything that isn't an integer. Depending on your needs, additional functionality like a regexp or substr() might be needed but that's up to you. Remember to get it into the right type first. b) I always include a default value in case the value does not exist from the input too. 3) Store data in its original form, do encoding/other things at runtime on output 4) Encode output (so the browser is not gven <script> tags but <script> for untrusted content for example)
When dealing with db queries, use mysql_escape_string or equivalent at runtime, prior to the query. Makes it easier to keep track of things that way, instead of escaping the data up top. example: # sanitizing, filtering $foo = filter_input(INPUT_GET, 'foo', FILTER_SANITIZE_STRING); # if default value is needed if(empty($foo)) { $foo = 'default value'; } # escaping - could make this into a single line too by using sprintf or other things. $foo = mysql_escape_string($foo); $result = db_query("SELECT foo FROM bar WHERE baz='$foo'"); for numeric input: # sanitizing, filtering - you'll get a type int with anything malicious scrubbed out already $foo = intval(filter_input(INPUT_GET, 'foo', FILTER_SANITIZE_NUMBER_INT)); # bounds checking examples (assume $maxpages has already been determined) if($foo < 0 || $foo > $maxpages) { redirect user back to foo.php?foo=1 } (pretend $foo is the page number. I could have made a better example there)