2009年3月23日星期一

PHP 中的 UTF8 和 Mysql

很多人在 Mysql 默认为非 UTF8 但要使用 UTF8 编码的时候会使用 "SET NAMES UTF8" 语句去设置正确的编码方式。通常为了方便在初始化 Db 对象或者创建连接后就去执行,虽然这种方式可以正确工作,但会导致一次连接和查询,即使初始化之后并无需要数据库。这也破坏了很多数据库对象提供的 lazy connect 特性。
PHP 手册不推荐使用 query() 去执行 SET NAMES

更好的方法是使用数据库驱动自身提供的特性去初始化编码。

mysql:
mysql_set_charset('utf8');

mysqli:
mysqli_set_charset($link, 'utf8'); //面向过程风格
$mysql->set_charset('utf8'); //或者面向对象风格
//也可以使用初始化命令
mysqli_options($link, MYSQLI_INIT_COMMAND, 'SET NAMES utf8'); //面向过程
$mysql->options(MYSQLI_INIT_COMMAND, 'SET NAMES utf8'); //面向对象


PDO:
//使用连接参数,MYSQL_ATTR_INIT_COMMAND 在连接后执行初始化命令,类似于 query 好处是仅在连接后执行一次
$pdo = new PDO("mysql:host=localhost;dbname=dbname",
'username', 'password',
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));


Zend_Db,Zend_Db 没有提供特殊的设置参数,只能使用初始化命令参数, 见 Mysqli 和 PDO 的 INIT_COMMAND:
//PDO 驱动
$params = array(
'host' => 'localhost',
'username' => 'username',
'password' => 'password',
'dbname' => 'dbname',
'driver_options' => array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8');
);
$db = Zend_Db::factory('Pdo_Mysql', $params);

//Mysqli 驱动:
$params = array(
'host' => 'localhost',
'username' => 'username',
'password' => 'password',
'dbname' => 'dbname',
'driver_options' => array(MYSQLI_INIT_COMMAND => 'SET NAMES UTF8');
);
$db = Zend_Db::factory('Mysqli', $params);