在$ PDO_OPTIONS中将PDO :: ATTR_EMULATE_PREPARES设置为False时出错

时间:2013-10-10 07:22:14

标签: php codeigniter pdo

我正在使用phpactiverecords和codeigniter。我想将PDO :: ATTR_EMULATE_PREPARES设置为false

我在第54行的文件PDO::ATTR_EMULATE_PREPARES => false中将 $PDO_OPTIONS 添加到 ../lib/Connection.php 。它导致未被捕获的例外:

../lib/adenter code hereapters/MysqlAdapter.php(76): ActiveRecord\Connection->query('SET NAMES ?', Array)

任何想法?

异常

  

致命错误:未捕获异常'ActiveRecord \ DatabaseException'   消息'42000, 1064, You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1'in   /home/waqas/apps/FBI-PHP/sparks/php-activerecord/0.0.2/vendor/php-activerecord/lib/Connection.php:304

堆栈跟踪:

0) /home/waqas/apps/FBI-PHP/sparks/php-activerecord/0.0.2/vendor/php-activerecord/lib/adapters/MysqlAdapter.php(76): ActiveRecord\Connection->query('SET NAMES ?', Array)

1) /home/waqas/apps/FBI-PHP/sparks/php-activerecord/0.0.2/vendor/php-activerecord/lib/Connection.php(108): ActiveRecord\MysqlAdapter->set_encoding('utf8')

2) /home/waqas/apps/FBI-PHP/sparks/php-activerecord/0.0.2/vendor/php-activerecord/lib/ConnectionManager.php(33): ActiveRecord\Connection::instance('mysql://root:@l...')

3) /home/waqas/apps/FBI-PHP/sparks/php-activerecord/0.0.2/vendor/php-activerecord/lib/Table.php(103): ActiveRecord\ConnectionManager::get_connection(NULL)

4) /home/waqas/apps/FBI-PHP/s in /home/waqas/apps/FBI-PHP/sparks/php-activerecord/0.0.2/vendor/php-activerecord/lib/Connection.php on line 304

1 个答案:

答案 0 :(得分:2)

设置连接编码的推荐方法是连接DSN中的charset属性:

$dsn = 'mysql:host=localhost;dbname=foo;charset=utf8';
$conn = new PDO($dsn, 'jim', '12345678', $options);

...但此功能需要PHP / 5.3.6或更高版本。您的库可能会尝试支持旧版本,因此请运行SQL命令。细节是你需要运行这个:

SET names=utf8

引用参数不起作用:

SET names='utf8'
  

错误1064(42000):您的SQL语法有错误;检查   手册,对应右边的MySQL服务器版本   在''

附近使用的语法

库正在使用预准备语句来运行查询。这是the offending code

public function set_encoding($charset)
{
    $params = array($charset);
    $this->query('SET NAMES ?',$params);
}

由于utf8是一个字符串,因此技术上需要引用它。所以(理论上)你不能使用预准备语句来运行这样的查询。在实践中,如果您使用模拟的预准备语句,它显然可以正常工作,但在您使用原生语句时则不然:

<?php

$dsn = 'mysql:host=localhost;dbname=test';
$user = 'test';
$pass = 'test';

// Works fine
$pdo = new PDO($dsn, $user, $pass, array(
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => true,
));
$res = $pdo->prepare('SET NAMES ?');
$res->execute(array('utf8'));
unset($pdo);

// Triggers SQL syntax error
$pdo = new PDO($dsn, $user, $pass, array(
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,
));
$res = $pdo->prepare('SET NAMES ?');
$res->execute(array('utf8'));
unset($pdo);

我的结论是,如果你想按原样使用库,那你就不走运了:PHP ActiveRecord似乎不支持本机预处理语句。

然而,一个简单的补丁可能会起到作用:

// Completely untested!
public function set_encoding($charset)
{
    $this->query('SET NAMES ' . $charset);
}

修改:我见过你的bug report。您也省略了异常消息。请注意,存在错误消息可以帮助您:您永远不应该丢弃它们!