【问题标题】:Error on setting PDO::ATTR_EMULATE_PREPARES to False in $PDO_OPTIONS在 $PDO_OPTIONS 中将 PDO::ATTR_EMULATE_PREPARES 设置为 False 时出错
【发布时间】:2013-10-17 20:14:18
【问题描述】:

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

我正在将 PDO::ATTR_EMULATE_PREPARES => false 添加到文件 ../lib/Connection.php 的第 54 行的 $PDO_OPTIONS 中。它在以下位置导致未捕获的异常:

../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'在 /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

【问题讨论】:

  • 它会导致什么异常?
  • 我添加了异常和堆栈跟踪。

标签: php codeigniter pdo


【解决方案1】:

设置连接编码的推荐方法是连接 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'

ERROR 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。您也省略了异常消息。请注意,存在帮助您的错误消息:您永远不应丢弃它们!

【讨论】:

  • 你是完全正确的。问题出在 php-activerecord/lib/adapters/MysqlAdapter.php 中。您提到的修复工作。
猜你喜欢
  • 2013-04-22
  • 1970-01-01
  • 2015-07-19
  • 2013-11-13
  • 2012-04-24
  • 1970-01-01
相关资源
最近更新 更多