【发布时间】:2014-05-02 02:15:40
【问题描述】:
我在使用 pdo_odbc 和 PDO::FETCH_OBJ(和 PDO::FETCH_CLASS)时遇到了一个奇怪的问题,导致出现以下错误消息:
PHP Fatal error: Cannot access empty property
代码如下:
$dbh = new PDO("odbc:FOO");
$sth = $dbh->query("
SELECT rolename
FROM dbc.allrolerights
WHERE databasename = 'BAR'
");
$result = $sth->fetch(PDO::FETCH_OBJ);
作为参考,FOO DSN 是使用 tdata.so 驱动程序的 Teradata 数据源,由 tdodbc 包提供。
我相信这是因为当 PDO 调用 zend_API.h:object_init_ex() 来实例化 stdClass 对象时,字段名称(从 ODBC 查询返回)是空白的。如果我切换到 PDO::FETCH_LAZY 和 var_dump() 行,我会得到以下信息:
object(PDORow)#3 (2) {
["queryString"]=>
string(95) "
SELECT rolename
FROM dbc.allrolerights
WHERE databasename = 'BAR'
"
[""]=>
string(30) "FNAR "
}
这似乎支持它。我尝试了几种不同的 PDO 属性组合和一堆不同的角度来解决这个问题。一种解决方案是获取关联数组并将其传递给类构造函数。但是,这不适用于在幕后直接使用 PDO::FETCH_CLASS 的某些框架和 ORM。
我想补充一点,其他 fetch 方法似乎做正确的事情,例如 PDO::FETCH_NAMED:
array(1) {
["RoleName"]=>
string(30) "FNAR "
}
我正在寻找可以放入 PDO dbh 或 sth 定义或数据源或驱动程序的 odbc.ini 或 odbcinst.ini 中的内容,以解决此问题。先感谢您。
更新: odbc_fetch_object()(即不是 PDO)适用于完全相同的所有内容。只是想提一下。显然 PHP、unixODBC 或 ODBC 驱动程序似乎没有任何严重问题。这是 PDO 代码中的内容。是时候打开错误报告了...opened
$dbh = odbc_connect("FOO", NULL, NULL)
or die(odbc_error_msg());
$sth = odbc_exec($dbh, "
SELECT rolename
FROM dbc.allrolerights
WHERE databasename = 'BAR'
");
$result = odbc_fetch_object($sth);
var_dump($result);
还有输出:
object(stdClass)#1 (1) {
["RoleName"]=>
string(30) "FNAR "
}
更新 2: 情况继续变得越来越离奇。我可以执行 PDO::FETCH_LAZY 并查看上面 var_dump() 中看到的空白列名,但如果我尝试按名称访问属性(例如 $result->RoleName),它就可以工作!这些 fetch 方法有何不同之处,以至于它们中的一些有时可以访问字段名称,而另一些则不能?
ODBC 跟踪的并排比较(“工作”比较“不工作”)显示没有差异(除了不同的指针地址)。 PDO::FETCH_BOUND 适用于编号列和命名列。 PDO::FETCH_INTO 具有 RoleName 属性的对象没有。
【问题讨论】:
-
尝试先升级PHP。
-
我试过 5.5.9。没有变化。
-
我可以建议两件事:您的
SELECT rolename不区分大小写是吗? PDO 可能会对此感到有些好笑。此外,如果您加入具有相同列的表,则该列可能根本不会返回,除非您在 SQL 中选择 dup 作为 dup1。还有一个最后的建议是尝试反引号'`'列名.. -
我尝试了不同的情况,甚至尝试设置 PDO::ATTR_CASE 来强制执行不同的行为,但没有任何变化。这是一个没有连接的简单选择,因此没有重复的列;别名列不会改变任何东西。我没有尝试过反引号,但这些不适用于 Teradata。我使用了双引号,这似乎是Teradata中引用保留字的正确方法,并且没有任何变化。谢谢!