PHP の PDO でキャラクタセットを指定するときは次の様に行なっています。
$pdo = new PDO("mysql:host=127.0.0.1;dbname=test", $username, $password, array( PDO::MYSQL_ATTR_READ_DEFAULT_FILE => '/etc/my.cnf', PDO::MYSQL_ATTR_READ_DEFAULT_GROUP => 'php', ));
Zend_Db の場合は次の様に 'driver_options' で指定します。
$db = Zend_Db::factory('Pdo_Mysql', array( 'host' => '127.0.0.1', 'username' => 'user', 'password' => 'pass', 'dbname' => 'test', 'driver_options' => array( PDO::MYSQL_ATTR_READ_DEFAULT_FILE => '/etc/my.cnf', PDO::MYSQL_ATTR_READ_DEFAULT_GROUP => 'php', ), ));
が、この方法を Windows版のPHP(5.3.3 と 5.3.13)で試してみたところ PDO::MYSQL_ATTR_READ_DEFAULT_FILE や PDO::MYSQL_ATTR_READ_DEFAULT_GROUP が定義されていないためにエラーになりました。
Fatal error: Undefined class constant 'MYSQL_ATTR_READ_DEFAULT_FILE'
リフレクションで見てみると、確かに PDO::MYSQL_* の定数の内、Windows版だと幾つかが定義されていませんでした(逆にWindows版だけで定義されているものもあり)。
拡張モジュールのソースを見てみると・・・「ext/pdo_mysql/pdo_mysql.c」で以下の通りになっていました。
static PHP_MINIT_FUNCTION(pdo_mysql) { REGISTER_INI_ENTRIES(); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_USE_BUFFERED_QUERY", (long)PDO_MYSQL_ATTR_USE_BUFFERED_QUERY); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_LOCAL_INFILE", (long)PDO_MYSQL_ATTR_LOCAL_INFILE); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_INIT_COMMAND", (long)PDO_MYSQL_ATTR_INIT_COMMAND); #ifndef PDO_USE_MYSQLND REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_MAX_BUFFER_SIZE", (long)PDO_MYSQL_ATTR_MAX_BUFFER_SIZE); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_READ_DEFAULT_FILE", (long)PDO_MYSQL_ATTR_READ_DEFAULT_FILE); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_READ_DEFAULT_GROUP", (long)PDO_MYSQL_ATTR_READ_DEFAULT_GROUP); #endif REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_COMPRESS", (long)PDO_MYSQL_ATTR_COMPRESS); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_DIRECT_QUERY", (long)PDO_MYSQL_ATTR_DIRECT_QUERY); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_FOUND_ROWS", (long)PDO_MYSQL_ATTR_FOUND_ROWS); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_IGNORE_SPACE", (long)PDO_MYSQL_ATTR_IGNORE_SPACE); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_KEY", (long)PDO_MYSQL_ATTR_SSL_KEY); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CERT", (long)PDO_MYSQL_ATTR_SSL_CERT); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CA", (long)PDO_MYSQL_ATTR_SSL_CA); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CAPATH", (long)PDO_MYSQL_ATTR_SSL_CAPATH); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CIPHER", (long)PDO_MYSQL_ATTR_SSL_CIPHER); return php_pdo_register_driver(&pdo_mysql_driver); }
PDO_USE_MYSQLND が定義されているかどうかで、PDOの定数の定義が変わるようです。
それでは PDO_USE_MYSQLND はどこで定義されているのか見てみると・・・「ext/pdo_mysql/config.m4」と「ext/pdo_mysql/config.w32」にありました。
ext/pdo_mysql/config.m4
if test "$PHP_PDO_MYSQL" = "mysqlnd"; then dnl enables build of mysqnd library PHP_MYSQLND_ENABLED=yes AC_DEFINE([PDO_USE_MYSQLND], 1, [Whether pdo_mysql uses mysqlnd])
ext/pdo_mysql/config.w32
if (PHP_PDO_MYSQL != "no") { if (PHP_PDO_MYSQL == "yes" || PHP_PDO_MYSQL == "mysqlnd") { AC_DEFINE('PDO_USE_MYSQLND', 1, 'Using MySQL native driver'); STDOUT.WriteLine("INFO: mysqlnd build"); EXTENSION("pdo_mysql", "pdo_mysql.c mysql_driver.c mysql_statement.c"); ADD_EXTENSION_DEP('pdo_mysql', 'pdo'); } else { if (CHECK_LIB("libmysql.lib", "pdo_mysql", PHP_PDO_MYSQL) && CHECK_HEADER_ADD_INCLUDE("mysql.h", "CFLAGS_PDO_MYSQL", PHP_PHP_BUILD + "\\include\\mysql;" + PHP_PDO_MYSQL)) { EXTENSION("pdo_mysql", "pdo_mysql.c mysql_driver.c mysql_statement.c"); } else { WARNING("pdo_mysql not enabled; libraries and headers not found"); } } }
m4 は詳しくありませんが、m4 の方だと特別指定しなければ libmysqlclient が使用され、w32 の方だと逆に mysqlnd が使われるようです(公式のWindows版バイナリも mysqlnd を使うようにビルドされている)。
CentOS5 の yum 版だと libmysqlclient の方でビルドされているので、Windowsでユニットテスト、プロダクションは CentOS などという場合に困りそうです。
dsn で charset を指定すれば解決な気もしますが、CentOS5 の yum 版が PHP-5.3.3 なので dsn に charset を指定しても効きませんし・・・