我知道准备好的陈述是要走的路,但我有一个很大的遗留应用程序,我正在转换。
我已经将它从mysqli更改为PDO作为第一步,现在将其中的所有查询转换为预准备语句。但是有数百个,所以需要时间。
在此期间,我应该使用什么函数来转义字符串?
我尝试了$PDO->quote
,但似乎做了两件事:
1)用引号括起一个字符串 2)转换'在字符串中\'
我可以轻松地修剪开始/结束报价,但最后我得到了结果。被插入数据库。我认为正确的逃避将是转换'到了',所以我不确定为什么要反斜杠?
我知道这是可怕的,但这是我在此期间提出的那个问题...
$s = str_replace("''","'",$s);
$s = str_replace("''","'",$s);
$s = str_replace("''","'",$s);
$s = str_replace("''","'",$s);
$s = str_replace("''","'",$s);
$s = str_replace("''","'",$s);
$s = str_replace("'","''",$s);
我应该做什么呢?而且,当我将所有内容转换为准备好的语句时,这是一个权宜之计。
这就是应用程序的用法,mysqli-style:
function SQLSafe($s) {
global $DB;
$s = get_magic_quotes_gpc() ? stripslashes($s) : $s;
$s = $DB->escape_string($s);
return $s;
}
其中$ DB是
$DB = new mysqli(DB_SERVER, DB_USER, DB_PASSWORD, DB_NAME);
$DB->set_charset('utf8');
$DB->query("SET NAMES 'utf8' COLLATE 'utf8_general_ci'");
并使用如下:
$DB->query("INSERT INTO USERS (username) VALUES ('" . SQLSafe($username) . "')");
答案 0 :(得分:0)
据我所知,mysqli_real_escape_string()
和PDO::quote()
在MySQL上下文中表现相似 - 唯一的区别是前者没有添加周围的引号,所以你这样使用它:
$email = mysqli_real_escape_string($conn, filter_input(INPUT_POST, 'email'));
$sql = "SELECT user_id, user_name
FROM user
WHERE email='$email'";
...后者确实添加了它们,所以你这样使用它:
$email = $pdo->quote(filter_input(INPUT_POST, 'email'));
$sql = "SELECT user_id, user_name
FROM user
WHERE email=$email";
如果修复SQL的查询太多,我建议你编写一个自定义包装函数并用它来搜索+替换mysqli_real_escape_string
调用,例如:
/**
* Emulates mysqli_real_escape_string()
*
* @param PDO $pdo
* @param mixed $input
* @return string Escaped input, not surrounded in quotes
*/
function pdo_real_escape_string (PDO $pdo, $input) {
$output = $pdo->quote($input);
return $output[0] === "'"
? mb_substr($output, 1, -1, 'utf-8' /* or whatever */)
: $output;
}
请注意这是一个丑陋的黑客和准备好的陈述是唯一明智的方法。例如,null
值将变为空字符串(''
)。它只是暂时取代同样丑陋的黑客。
每个数据库驱动程序实现(或不执行)PDO::quote()
也没有任何价值。这意味着驱动程序作者可以选择如何解释文档的这一部分:
PDO::quote()
在输入字符串周围添加引号(如果需要) 并使用a转义输入字符串中的特殊字符 引用适合底层驱动程序的样式。
一些快速测试表明MySQL驱动程序总是添加这样的引号,但是YMMV。
答案 1 :(得分:0)
我倾向于回答你所遇到的真正问题,而不是因为错误的转弯你偶然发现的XY问题。
如果您确实从 mysqli 而不是mysql ext转换,那么您可以使用mysqli并使用此扩展的内置预准备语句。只需确保系统中存在mysqli_stmt::get_result()
方法。
如果它不是mysqli而是基于mysql ext的代码,你实际上是在重写,那么我认为你的目标是渐进式重写没有意义。只需坐下来重写每个PDO准备好的语句。 你必须重写你的所有代码,即使你用这种奇怪的方法从PDO引用中删除引号。为什么两次做同样的工作?
答案 2 :(得分:0)
我现在可以看到我遇到的问题只是我错误地将字符串传递了O'Hare
两次。因此,O\'Hare
成为第一个O\\\'Hare
,然后是function SQLSafe($s) {
global $PDO;
return substr($PDO->quote($s), 1, -1);
}
。这就是我在数据库中以反斜杠结束的原因,这是我的错误,并且我正在使用的PDO->引用函数没有错。
所以这个功能现在只是:
get_magic_quotes_gpc
(我删除了关于function SQLSafe(string $s): string
{
global $PDO;
$s = $PDO->quote($s);
if ($s[0] === "'") {
$s = substr($s, 1, -1);
}
return $s;
}
的行,因为它总是从php5.4返回FALSE)
好的,在对数值数据发表评论后,我已将其更改为
Day, Month, Year