PDO 连接:带有 SET NAMES / CHARACTER SET 的 UTF-8 声明?

Posted

技术标签:

【中文标题】PDO 连接:带有 SET NAMES / CHARACTER SET 的 UTF-8 声明?【英文标题】:PDO connection : UTF-8 declaration with SET NAMES / CHARACTER SET? 【发布时间】:2012-12-12 02:57:05 【问题描述】:

根据 php.net、Stack Overflow 和其他信任来源,我可以找到 4 种在 PDO 连接上设置 UTF-8 的不同方式,但找不到哪个更好选择:

$pdo_db = 'mysql:host=localhost;dbname=local_db;charset=utf8'; // METHOD #1
$pdo_login = 'root';
$pdo_pass = 'localpass';

$db = new PDO($pdo_db, $pdo_login, $pdo_pass, array(
    PDO::ATTR_ERRMODE => $localhost ? PDO::ERRMODE_EXCEPTION : PDO::ERRMODE_SILENT,
    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', // METHOD #2
));
$db->exec('SET NAMES utf8'); // METHOD #3
$db->exec('SET CHARACTER SET utf8'); // METHOD #4

所以,我的理解是,方法 1 仅适用于 PHP 5.3+(但似乎有点错误),方法 2 仅适用于 MySQL。 方法3和4的区别是MySQL thing,但是我还是不知道哪个更好。有没有办法在 PDO 属性中调用 SET NAMES,但不能只用于 MySQL?

【问题讨论】:

【参考方案1】:

在 DSN 中设置它是唯一正确的方法(尽管它仅从 5.3 开始受支持)。 这个可以和SET NAMES同时使用。

所有其他方式都将使臭名昭著的半虚构 GBK 注入成为可能。

请注意,您对 error_reporting() 的设置完全错误。它必须是无条件的-1。 如果您担心显示错误 - 有一个适当的 ini 设置,称为 display_errors,可以在运行时设置。 而error_reporting 设置错误的级别,并且应该一直处于最大值。

【讨论】:

所以对于 听起来完全正确!所以第二行变成error_reporting(-1); ini_set('display_errors', $localhost); @Dharman 有一个关于SQL injecton goes around escaping 的老故事。半虚构,因为没有人在野外见过它,特别是因为 utf-family 编码据说是免疫的。因此,为了避免在某些 exotc 编码中注入,不仅要为 PHP 驱动程序的连接机器人设置字符集。所以 mysql_set_charset 和 DSN 中的设置。 @Dharman 哦,是的,在禁用仿真的情况下,这根本不重要 @Dharman 5.3 之前的仿真如果您必须使用 GBK 或其他类似知名的编码,则完全容易发生 SQL 注入【参考方案2】:

我总是在我的 dbconfig 文件中写下这些代码:

mysql_query("SET character_set_results = 'utf8',
                 character_set_client = 'utf8', 
                 character_set_connection = 'utf8',
                 character_set_database = 'utf8',  
                 character_set_server = 'utf8'");

【讨论】:

是的,但是 pdo 呢? OP 不应该更喜欢 PDO 或 mysqli 解决方案吗? 那么SET NAMES 'utf8' COLLATE 'utf8_general_ci' 是那个的捷径吗? @Didjo 是的,但它也控制来自 Web 界面的所有输入和输出

以上是关于PDO 连接:带有 SET NAMES / CHARACTER SET 的 UTF-8 声明?的主要内容,如果未能解决你的问题,请参考以下文章

带有 PDOStatement 的 PDO 重新连接“mysql 服务器消失”错误

使用 PDO 连接 MySQL

DB2如何使用PDO指定连接字符集

带有连接表的 PDO FETCH_CLASS

PDO 连接和抽象类

使用带有 PDO 的数组更新多个 MySQL 表列