断续器
// The key is the "charset=utf8" part.
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';
$dbh = new PDO($dsn, 'user', 'pass');
这个答案强调php的pdo库,因为它是无处不在的。
简要提醒 - mysql是一种客户端 - 服务器架构。这很重要,因为不仅有实际数据库所在的mysql服务器,还有单独的mysql客户端驱动程序,这是与mysql服务器通信的东西(它们是单独的实体)。你可以说mysql客户端和pdo混合在一起。
使用 时,可以向 mysql 发出标准 sql 查询。虽然sql查询确实通过pdo,然后通过mysql客户端库,然后最终到达mysql服务器,但只有mysql服务器解析并解释该sql查询。这很重要,因为mysql服务器不会将任何消息发送回pdo或mysql客户端,让它知道字符集和编码已更改,因此mysql客户端和pdo都完全不知道它发生了。set names utf8
请务必不要这样做,因为如果客户端库不知道当前字符集,则无法正确处理字符串。大多数常见操作在客户端不知道正确字符集的情况下可以正常工作,但字符串转义(如 PDO::quote)则无法正常工作。您可能认为您不必担心这种手动原始字符串转义,因为您使用了预准备语句,但事实是绝大多数pdo:mysql用户在不知不觉中使用模拟的预准备语句,因为它已经是pdo:mysql驱动程序的默认设置很长一段时间了。模拟的预准备语句不使用 mysql api 提供的真正本机 mysql 预准备语句;相反,php相当于调用所有值,并str_replacing所有占位符,并为您引用值。PDO::quote()
由于除非您知道正在使用的字符集,否则无法正确转义字符串,因此,如果您通过 更改为某些字符集,则这些模拟的预准备语句容易受到 sql 注入的影响。无论 sql 注入的可能性如何,如果使用用于不同字符集的转义方案,您仍然可以中断字符串。set names
对于 pdo mysql 驱动程序,可以在连接时通过在 DSN 中指定字符集来指定字符集。如果您这样做,客户端库和服务器都将知道字符集,因此事情将按预期方式工作。
// The key is the "charset=utf8" part.
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';
$dbh = new PDO($dsn, 'user', 'pass');
但是,不正确的字符串转义并不是唯一的问题。例如,使用 PDO::bindColumn 也可能遇到问题,因为列名被指定为字符串,因此编码也很重要。一个例子可以是一个名为(注意元音变音符)的列名,然后你通过集合名称切换到,然后你尝试成为一个utf8编码的字符串,因为你的php文件是utf8编码的。它不起作用,您需要将字符串编码为latin1变体...现在你有各种各样的疯狂在发生。ütube
latin
utf8
$stmt->bindColumn('ütube', $var);
ütube