我真的应该使用 PDO 和准备好的语句吗?

问题描述 投票:0回答:6

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

php mysql pdo
6个回答
10
投票

可以,但 PDO 和准备好的语句绝对是最安全的。您可以手动完成并使用

mysql_real_escape_string()
功能吗?当然。事实上,您的输出可能看起来相同。但最终,PDO 所需的代码将比手动完成的代码短得多。

此外,如果您不使用准备好的语句,则会面临人为错误的风险:比如说您忘记转义值或清理输入。与所有其他代码混合在一起,没有正确清理的一行可能会成为未来的一场噩梦。


3
投票

我真的很喜欢 PDO 界面。一旦你习惯了它,它比 mysql_* 函数风格干净得多。 我也花了一段时间才弄清楚,但这是值得的。

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

通过某些操作,您还可以通过重复准备好的语句来获得性能优势。例如,如果您在循环中执行大量插入,则可以准备语句,然后每次插入之前在循环中绑定新数据。

安全性也好得多,因为您依赖于经过良好测试的库来转义每次插入时的数据。这就像密码学——既然如此重要,为什么要自己做呢?没有理由给自己一个犯错的机会(即意外地错过转义插入到查询中的内容)。

我向 PDO 推荐 本指南,来自撰写这本有关 Mysql 的优秀巨著的作者。

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

$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
投票

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

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

IN( )
谓词的参数)。

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

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


0
投票
使用 PDO/准备好的语句。

虽然,我个人建议使用 PDO/准备好的语句,因为它们确实使开发/调试更容易,并且准备好的语句甚至可以防止不正确的数据类型进入查询。 如果您想了解有关如何创建简单的准备语句的更多信息,请查看该函数sprintf

。您只需用类型说明符替换任何变量字符串、整数等(在本例中分别为

%s

%d
)。
因此,例如在下面的查询中,我知道 
id

将是一个整数(它将是数字)而

name

 将是一个字符串(字母数字)。
$username = 'Simon';
$id       = 3;
$query    = "SELECT FROM `users` WHERE `id` = {$id} AND `name` = '{$username}'";

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

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

sprintf
不会让我在调用时使用字符串作为 $id 或使用整数作为 $name,这可以确保给出正确的数据类型(这给了我一点额外的安全性)。如果给出了不正确的数据类型,那么

我相信

它将把变量转换为请求的类型。
要了解有关 sprintf

的更多信息,请访问此处:

http://php.net/sprintf



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

你可以尝试 zend_db,它在底层使用 pdo。 (

0
投票
是您可以使用的另一个选项。)

PHP 可以让你做任何你想做的事情,而 PDO 恰好可以用更少的代码做“你想做的”事情。 :)

0
投票

© www.soinside.com 2019 - 2024. All rights reserved.