在 Doctrine DBAL 中设置连接字符集并与 PHP PDO 进行比较

Setting connection charset in Doctrine DBAL with comparison to PHP PDO

是否需要将 set names ourcharset 与 DBAL 与 PHP >=5.3.2 and <5.3.6 一起使用?

在 PHP 5.3.6 之前,PDO 连接中的字符集选项是 ignored
如果我们 运行 是 PHP 的旧版本,我们必须使用 set names ourcharset.

实际学说 DBAL 2.5.1 require PHP >=5.3.2.
如果有人 PHP <5.3.6 版本,我找不到 Doctrine 团队的建议。

DBAL 主要基于 PDO,但它也有一些改进,所以我在想这可能有所改进......但是在 Doctrine DBAL documentation page 我只发现了这个:

Up until PHP 5.3.6 PDO has a security problem when using non ascii compatible charsets. Even if specifying the charset using “SET NAMES”, emulated prepared statements and PDO#quote could not reliably escape values, opening up to potential SQL injections. If you are running PHP 5.3.6 you can solve this issue by passing the driver option “charset” to Doctrine PDO MySQL driver. Using SET NAMES does not suffice!

在PDO中到现在我做了:

<?php
$dsn = 'mysql:host='.$_SESSION['options']['host'].';port='.$_SESSION['options']['port'].';dbname='.$_SESSION['options']['dbname'].';charset='.$_SESSION['options']['charset'];
try {
    $conn = new \PDO($dsn, $_SESSION['options']['user'], $_SESSION['options']['pass']);
    if(version_compare(PHP_VERSION, '5.3.6', '<')) //is this required with DBAL? 
        $conn->exec("set names {$_SESSION['options']['charset']}");
} catch (\PDOException $e) {
    trigger_error($e->getMessage(), E_USER_ERROR);
}
?>

对于 DBAL,它是:

<?php
require_once "lib/autoload.php";
$config = new \Doctrine\DBAL\Configuration();
$params = array(
    'dbname' => $_SESSION['options']['dbname'],
    'user' => $_SESSION['options']['user'],
    'password' => $_SESSION['options']['pass'],
    'host' => $_SESSION['options']['host'],
    'port' => $_SESSION['options']['port'],
    'driver' => 'pdo_mysql',
    'charset' => $_SESSION['options']['charset'],
);
try {
    $conn = \Doctrine\DBAL\DriverManager::getConnection($params, $config);
} catch (\Exception $e) {
    trigger_error($e->getMessage(), E_USER_ERROR);
}
?>

看来 DBAL 在这里没有任何改进。 因此,如果我们的应用程序有可能在 >=5.3.2 and <5.3.6 之间使用 PHP,那么可以,使用额外的 SET NAMES:

<?php
require_once "lib/autoload.php";
$config = new \Doctrine\DBAL\Configuration();
$params = array(
    'dbname' => $_SESSION['options']['dbname'],
    'user' => $_SESSION['options']['user'],
    'password' => $_SESSION['options']['pass'],
    'host' => $_SESSION['options']['host'],
    'port' => $_SESSION['options']['port'],
    'driver' => 'pdo_mysql',
    'charset' => $_SESSION['options']['charset'],
);
if(version_compare(PHP_VERSION, '5.3.6', '<'))
    $params['driverOptions'] = array(1002=>'SET NAMES '.$_SESSION['options']['charset']); 
                                //"1002" is value of constant MYSQL_ATTR_INIT_COMMAND
try {
    $conn = \Doctrine\DBAL\DriverManager::getConnection($params, $config);
} catch (\Exception $e) {
    trigger_error($e->getMessage(), E_USER_ERROR);
}
?>