看起来我的另一个答案没有达到问题的目的。
(这个也不符合某些要求,但是可以看出,如果没有实现处理占位符的函数,就无法实现安全查询的基石)
因此,这里是另一种尝试发布简洁解决方案以使mysql查询既安全又方便。
我写了一个函数很久以前,它一直为我服务,直到我转向企业标准的基于OOP的解决方案。
有两个目标要追求:安全性和易用性。
第一个目标通过实现占位符来实现。
第二个目标通过实现占位符和不同的结果类型来实现。
该函数肯定不是理想的。一些缺点是:
- 不需要直接在查询中放置
%
字符,因为它使用printf语法。
- 不支持多个连接。
- 没有标识符的占位符(以及许多其他方便的占位符)。
- 再次强调,没有标识符的占位符!必须手动处理
"ORDER BY $field"
的情况!
- 当然,面向对象的实现会更加灵活,具有整洁的独立方法,而不是丑陋的“模式”变量和其他必要的方法。
尽管如此,它仍然很好、安全、简洁,无需安装整个库。
function dbget() {
$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;
}
它可以涵盖几乎所有需要,包括来自OP的示例案例。
#error_reporting(~E_ALL); ... to disable error output
- bad advice.” 这是个糟糕的建议,禁用错误输出应该避免使用这种方式。“Can't downvote more, else I would -1 for@
operator.” 如果能再多投票,我会给“@”运算符投反对票。 - OZ_@
符号总是抑制错误输出,这被视为不好的做法。我不理解的是对于error_reporting(~E_ALL);
的批评。 - Pekka