看起来我的其他答案没有达到问题的目的。
(这个也不满足一些要求,但可以看出,如果不实现处理占位符的功能,就无法实现安全的解决方案,占位符是安全查询的基石)
因此,这是另一个尝试发布简洁的解决方案以使 mysql 查询安全且方便。
我很久以前编写的一个函数,在我转向基于公司标准 OOP 的解决方案之前,它对我很有用。
有 2 个目标要追求:安全和易用性。
第一个通过实现占位符实现。
第二个是通过实现占位符和不同的结果类型来实现的。
功能肯定不理想。一些缺点是:
- 没有
% 字符必须直接放在查询中,因为它使用 printf 语法。
- 不支持多个连接。
- 没有标识符的占位符(以及许多其他方便的占位符)。
- 同样,没有标识符占位符!。
"ORDER BY $field" 案件需人工处理!
- 当然,OOP 实现会更加灵活,具有简洁的不同方法,而不是丑陋的“模式”变量以及其他必要的方法。
但它很好,安全简洁,无需安装整个库。
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;
}
?>
使用示例
$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);
从上面的例子可以看出,与Stackoverflow中发布的所有代码的主要区别在于,安全和数据检索例程都封装在函数代码中。因此,无需手动绑定、转义/引用或强制转换,也无需手动数据检索。
结合其他辅助功能
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);
}
这样使用
$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
}
它可能涵盖几乎所有需求,包括来自 OP 的示例案例。