Zend Framework+MySQLの文字化け対策

PHP5 + Zend Framework 1.9.2 + MySQL5 で、DBからデータを取得したときに文字化けするのを防ぐ方法について。

以下のように「set names utf8」を先に発行しておけば文字化けは防げるが、汎用的な Zend_Db を使っている以上、やはり MySQL 特有のコマンドは使いたくないしSQLインジェクションを引き起こす可能性があります。(参考 SET NAMESは禁止:http://blog.ohgaki.net/set_namesa_mcb_asc

$db = Zend_Db::factory('Pdo_Mysql', array(
        'host'          => 'xxx.xxx.xxx.xxx',
        'username'      => 'xxx',
        'password'      => 'xxx',
        'dbname'        => 'xxx'
));

$db->query("set names utf8");

そこで調べてみると、factory() のパラメータに charset を指定できることが判明。以下のようにすると、文字化けを防ぐことができました。

$db = Zend_Db::factory('Pdo_Mysql', array(
        'host'          => 'xxx.xxx.xxx.xxx',
        'username'      => 'xxx',
        'password'      => 'xxx',
        'dbname'        => 'xxx',
        'charset'       => 'utf8'
));

これでよしよし・・・と思ったのですが、念のため Zend Frameworkソースコード(Zend/Db/Adapter/Pdo/Mysql.php)を見てみると、「set names xxx」を使っているじゃないですか! PDO の driver_options パラメータに「set names xxx」を渡していました。SQLインジェクションは大丈夫なのでしょうか・・・?
以下がソースコードの一部引用です。

protected function _connect()
{
    if ($this->_connection) {
        return;
    }

    if (!empty($this->_config['charset'])) {
        $initCommand = "SET NAMES '" . $this->_config['charset'] . "'";
        $this->_config['driver_options'][1002] = $initCommand; // 1002 = PDO::MYSQL_ATTR_INIT_COMMAND
    }

    parent::_connect();
}

ちょっと不安なので、Pdo_Mysql ではなく Mysqli を使うことに。これで文字化けせずにうまく動きました。

$db = Zend_Db::factory('Mysqli', array(
        'host'          => 'xxx.xxx.xxx.xxx',
        'username'      => 'xxx',
        'password'      => 'xxx',
        'dbname'        => 'xxx',
        'charset'       => 'utf8'
));

Mysqli の ソースコード(Zend/Db/Adapter/Mysqli.php)を見ると、mysqli_set_charset() で文字コードをセットしていました。これを使えば、SQLインジェクションは大丈夫なようです。