我之前在我的正常mysql_*连接中有这个:

mysql_set_charset("utf8",$link);
mysql_query("SET NAMES 'UTF8'");

我需要它来做PDO吗?我应该把它放在哪里?

$connect = new PDO("mysql:host=$host;dbname=$db", $user, $pass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));

当前回答

我认为你需要一个额外的查询,因为DSN中的字符集选项实际上被忽略了。请看其他答案评论中的链接。

看看Drupal 7是如何在http://api.drupal.org/api/drupal/includes--database--mysql--database.inc/function/DatabaseConnection_mysql%3A%3A__construct/7:上实现的

// Force MySQL to use the UTF-8 character set. Also set the collation, if a
// certain one has been set; otherwise, MySQL defaults to 'utf8_general_ci'
// for UTF-8.
if (!empty($connection_options['collation'])) {
  $this->exec('SET NAMES utf8 COLLATE ' . $connection_options['collation']);
}
else {
  $this->exec('SET NAMES utf8');
}

其他回答

在PHP 5.3.6之前,charset选项被忽略。如果你运行的是旧版本的PHP,你必须这样做:

<?php

    $dbh = new PDO("mysql:$connstr",  $user, $password);

    $dbh -> exec("set names utf8");

?>

你会把它放在你的连接字符串中,像这样:

"mysql:host=$host;dbname=$db;charset=utf8mb4"

然而,在PHP 5.3.6之前,charset选项是被忽略的。如果你运行的是旧版本的PHP,你必须这样做:

$dbh = new PDO("mysql:host=$host;dbname=$db",  $user, $password);
$dbh->exec("set names utf8mb4");

为了完整起见,在从PDO连接到MySQL时,实际上有三种方法来设置编码,哪种方法可用取决于您的PHP版本。优先顺序为:

DSN字符串中的字符集参数 带PDO::MYSQL_ATTR_INIT_COMMAND连接选项运行SET NAMES utf8 手动执行SET NAMES utf8命令

这个示例代码实现了这三个:

<?php

define('DB_HOST', 'localhost');
define('DB_SCHEMA', 'test');
define('DB_USER', 'test');
define('DB_PASSWORD', 'test');
define('DB_ENCODING', 'utf8');


$dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_SCHEMA;
$options = array(
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
);

if( version_compare(PHP_VERSION, '5.3.6', '<') ){
    if( defined('PDO::MYSQL_ATTR_INIT_COMMAND') ){
        $options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES ' . DB_ENCODING;
    }
}else{
    $dsn .= ';charset=' . DB_ENCODING;
}

$conn = @new PDO($dsn, DB_USER, DB_PASSWORD, $options);

if( version_compare(PHP_VERSION, '5.3.6', '<') && !defined('PDO::MYSQL_ATTR_INIT_COMMAND') ){
    $sql = 'SET NAMES ' . DB_ENCODING;
    $conn->exec($sql);
}

同时做这三件事可能有点过头了(除非您正在编写一个计划发布或重用的类)。

$conn = new PDO("mysql:host=$host;dbname=$db;charset=utf8", $user, $pass);

这可能是最优雅的方法了。 就在PDO构造函数调用中,但避免了错误的charset选项(如上所述):

$connect = new PDO(
  "mysql:host=$host;dbname=$db", 
  $user, 
  $pass, 
  array(
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
  )
);

对我来说很好。