Looks like my other answer missed the aim of the question.
(this one doesn't meet some requirements either, but as it can be seen, no safe solution can be achieved without implementing a function to process placeholders, which are being the cornerstone of the safe queries)
So, here is another attempt to post concise solution to make mysql queries safe yet handy.
A function I wrote long time ago and it served me well until I moved to the corporative standard OOP-based solution.
There was 2 goals to pursue for: security and ease of use.
First one achieved by implementing placeholders.
Second one achieved by implementing placeholders and different result types.
The function surely not ideal one. Some drawbacks are:
- no
%
chars have to be placed in the query directly as it's using printf syntax.
- no multiple connections supported.
- no placeholder for the identifiers (as well as many other handy placeholders).
- again, no identifier placeholder!.
"ORDER BY $field"
case have to be handled manually!
- of course an OOP implementation would be much more flexible, having neat distinct methods instead ugly "mode" variable as well other necessary methods.
Yet it is good, safe and concise, no need to install a whole library.
function dbget() {
/*
usage: dbget($mode, $query, $param1, $param2,...);
$mode - "dimension" of result:
0 - resource
1 - scalar
2 - row
3 - array of rows
*/
$args = func_get_args();
if (count($args) < 2) {
trigger_error("dbget: too few arguments");
return false;
}
$mode = array_shift($args);
$query = array_shift($args);
$query = str_replace("%s","'%s'",$query);
foreach ($args as $key => $val) {
$args[$key] = mysql_real_escape_string($val);
}
$query = vsprintf($query, $args);
if (!$query) return false;
$res = mysql_query($query);
if (!$res) {
trigger_error("dbget: ".mysql_error()." in ".$query);
return false;
}
if ($mode === 0) return $res;
if ($mode === 1) {
if ($row = mysql_fetch_row($res)) return $row[0];
else return NULL;
}
$a = array();
if ($mode === 2) {
if ($row = mysql_fetch_assoc($res)) return $row;
}
if ($mode === 3) {
while($row = mysql_fetch_assoc($res)) $a[]=$row;
}
return $a;
}
?>
usage examples
$name = dbget(1,"SELECT name FROM users WHERE id=%d",$_GET['id']);
$news = dbget(3,"SELECT * FROM news WHERE title LIKE %s LIMIT %d,%d",
"%$_GET[search]%",$start,$per_page);
As it can be seen from the above examples, the main difference from all the codes ever posted in Stackoverflow, both safety and data retrieval routines are encapsulated in the function code. So, no manual binding, escaping/quoting or casting, as well as no manual data retrieval.
combined with other helper function
function dbSet($fields,$source=array()) {
$set = '';
if (!$source) $source = &$_POST;
foreach ($fields as $field) {
if (isset($source[$field])) {
$set.="`$field`='".mysql_real_escape_string($source[$field])."', ";
}
}
return substr($set, 0, -2);
}
used like this
$fields = explode(" ","name surname lastname address zip phone regdate");
$_POST['regdate'] = $_POST['y']."-".$_POST['m']."-".$_POST['d'];
$sql = "UPDATE $table SET ".dbSet($fields).", stamp=NOW() WHERE id=%d";
$res = dbget(0,$sql, $_POST['id']);
if (!$res) {
_503;//calling generic 503 error function
}
it may cover almost every need, including the example case from the OP.