我真的应该使用PDO和准备好的声明吗?

时间:2010-01-10 22:52:30

标签: php mysql pdo

PDO和准备好的陈述对我来说仍然有点混乱,无论我到目前为止读到了多少。所以我知道他们更“安全”,但它真的那么重要吗?我的意思是我可以使用mysql_real_escape_string()和htmlspecialchars()的基本mysql获得相同的最终结果吗?

6 个答案:

答案 0 :(得分:10)

你可以,但PDO和准备好的陈述是绝对最安全的。你能用手工做并使用mysql_real_escape_string()功能吗?当然。实际上,您的输出可能看起来相同。但最后,如果您手动完成,那么PDO所需的代码将比代码短得多。

此外,如果您没有使用预准备语句,则存在人为错误的风险:假设您忘记转义值或清理输入。与你的所有其他代码混合在一起,没有正确消毒的那一行可能会成为一场噩梦。

希望这有帮助!

答案 1 :(得分:3)

我非常喜欢PDO界面。一旦你习惯它,它比mysql_ *函数风格更清晰。我花了一段时间来弄清楚它,但这是值得的。

我发现令人困惑的部分是记住哪些方法属于PDO DB连接对象本身,哪些是语句对象的一部分。

通过某些操作,您也可以通过重复预备语句获得性能优势。例如,如果你在循环中做了一堆插入,你可以准备语句,然后在每次插入之前在循环中绑定新数据。

安全性也好得多,因为你依靠经过良好测试的库来逃避每个插入数据。这就像加密 - 为什么要自己做,什么时候这很重要?没有理由给自己一个错误的机会(即,意外地错过了插入查询中的内容)。

我向撰写此this guide的作者推荐excellent giant book on Mysql到PDO。

我喜欢使用位置参数样式,然后你只需要创建一个数组数组并将其传入。我的查询看起来像

$pdo_db=pdo_connect('cow_db');
$sql='select this,that,count(those) as snout from lovely_table where name=? and horses=?';
$data=array($username,$horse_count);

$query_stmt=$pdo_db->prepare($sql);
$result_handle=$query_stmt->execute($data);

//then I have a function to load data from the result handle
$info=load_array($result_handle);

你可以使用这样的函数来使用标准的php mysql接口,但为什么不使用PDO?

答案 2 :(得分:2)

我同意其他人说使用准备好的查询通常比使用转义函数更好。它更容易正确使用,并且参数值无法引入SQL注入问题,因为该值与SQL查询分开发送到RDBMS服务器。

但是,仅当SQL查询的动态部分是表示表达式中的文字值的参数时,使用参数才有用。您不能使用查询参数代替表名,列名,SQL表达式或值列表(例如IN( )谓词的参数)。

准备好的查询还比非准备好的查询(至少在MySQL中)具有更好的性能。大多数人都说相反,但备受推崇的mysqlperformanceblog.com进行了测试:

http://www.mysqlperformanceblog.com/2006/08/02/mysql-prepared-statements/

答案 3 :(得分:0)

只要您为查询正确清理数据,就不会 使用PDO /预编译语句。 虽然,我个人建议使用PDO /预处理语句只是因为它们都使开发/调试变得更容易,并且准备好的语句可以防止不正确的数据类型进入查询。

如果您想了解有关如何创建简单预处理语句的更多信息,请查看函数sprintf。您只需使用类型说明符替换任何变量字符串,整数等(分别为%s%d)。

例如,在下面的查询中,我知道id将是一个整数(它将是数字),name将是一个字符串(字母数字)。

$username = 'Simon';
$id       = 3;
$query    = "SELECT FROM `users` WHERE `id` = {$id} AND `name` = '{$username}'";

如果我从不受信任的来源(例如POST / GET)中获取这些变量中的任何一个,那么我可以通过将最后一行($ query set)替换为一个来确保它们是正确的数据类型sprintf这样称呼:

$username = 'Simon';
$id       = 3;
$query    = sprintf( "SELECT FROM `users` WHERE `id` = %d AND `name` = '%s'", $id, $username );

sprintf只是不允许我在调用$ name时使用字符串作为$ id或$ name的整数,以确保给出正确的数据类型(这给了我额外的安全性) )。如果给出了不正确的数据类型,那么我相信它会将变量转换为所请求的类型。

要详细了解sprintf,请访问:http://php.net/sprintf

我希望这足以解释(这是我的第一个答案):)。

答案 4 :(得分:0)

你可以尝试使用pdo的zend_db。 (mdb2是您可以使用的另一种选择。)

答案 5 :(得分:0)

PHP可以让你做任何你想做的事情,而事实上,PDO可以用更少的代码完成“你想要的”。 :)