为什么这些准备好的陈述不起作用?

时间:2009-12-22 14:29:44

标签: php pdo prepared-statement

我使用NetBeans 6.8并在我的mac上使用此配置的MAMP:

Apache 2.0.63
MySQL 5.1.37
PHP 4.4.9 & 5.2.10
APC 3.0.19 & APC 3.1.2
eAccelerator 0.9.5.3
XCache 1.2.2
phpMyAdmin 2.11.9.5 & phpMyAdmin 3.2.0.1
Zend Optimizer 3.3.3
SQLiteManager 1.2.0
Freetype 2.3.9
t1lib 5.1.2
curl 7.19.5
jpeg 7
libpng-1.2.38
gd 2.0.34
libxml 2.7.3
libxslt 1.1.24
gettext 0.17
libidn 1.15
iconv 1.13
mcrypt 2.5.8
YAZ 3.0.47 & PHP/YAZ 1.0.14

My PDO Driver for MySQL是客户端库版本5.1.37

我尝试在这里使用预备语句。

这完全没有准备好的陈述:

try {
    $dbh = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
    $prepared = $dbh->prepare('SELECT * from sys_navigation_point WHERE name="root"');
    //$prepared->bindParam('foo', 'root');

    $prepared->execute();

    foreach($prepared as $row) {
        print_r($row);
    }
    $dbh = null;
} catch (PDOException $e) {
    print "Error!: " . $e->getMessage() . "<br/>";
    die();
}

但这对于准备好的声明根本不起作用。在执行此操作时获取完全空白的页面:

try {
    $dbh = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
    $prepared = $dbh->prepare('SELECT * from sys_navigation_point WHERE name=:foo');
    $prepared->bindParam('foo', 'root');

    $prepared->execute();

    foreach($prepared as $row) {
        print_r($row);
    }
    $dbh = null;
} catch (PDOException $e) {
    print "Error!: " . $e->getMessage() . "<br/>";
    die();
}

应该用root替换foo。但事实并非如此。好吧,让我们尝试一下,这根本不起作用:

try {
    $dbh = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
    $prepared = $dbh->prepare('SELECT * from sys_navigation_point WHERE name=?');
    $prepared->bindParam(1, 'root');

    $prepared->execute();

    foreach($prepared as $row) {
        print_r($row);
    }
    $dbh = null;
} catch (PDOException $e) {
    print "Error!: " . $e->getMessage() . "<br/>";
    die();
}

绝对没有。我甚至没有收到错误消息。只是一个空白页面。在此代码之后,标准HTML输出有一些回声。它没有出去,所以脚本停在bindParam方法调用附近的某处。

同样,这个完美无缺,没有任何准备好的陈述:

try {
    $dbh = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
    $prepared = $dbh->prepare('SELECT * from sys_navigation_point WHERE name="root"');
    //$prepared->bindParam('foo', 'root');

    $prepared->execute();

    foreach($prepared as $row) {
        print_r($row);
    }
    $dbh = null;
} catch (PDOException $e) {
    print "Error!: " . $e->getMessage() . "<br/>";
    die();
}

您可以看到,显然所有版本都是完全相同的查询。用PS不起作用。没有PS就可以了。现在我在PHP本身发现了一个残酷的错误?

是否有可能在某处禁用预准备语句?

2 个答案:

答案 0 :(得分:3)

您正在使用此类代码:

$prepared->bindParam('foo', 'root');

bindParam期待变量作为第二个参数:

bool PDOStatement::bindParam  ( mixed $parameter  , 
    mixed &$variable  [, int $data_type = PDO::PARAM_STR  [, int $length  
    [, mixed $driver_options  ]]] )


在这里,您应该使用bindValue,因为您只想绑定...值...而不是通过引用SQL查询传递的变量:

bool PDOStatement::bindValue  ( mixed $parameter  , mixed $value  
    [, int $data_type = PDO::PARAM_STR  ] )

所以,你的代码看起来像是:

$prepared->bindValue(':foo', 'root');

(不要忘记参数名称之前的':',顺便说一句;-))

答案 1 :(得分:2)

绑定名称为:foo - 而不是foo。并且您不应该使用bindParam,而是使用bindValue,因为您没有将变量作为参数。例如。 :

$prepared->bindValue(':foo', 'root');

一般情况下,我建议您永远使用bindParam,因为它具有引用语义,因此可能会产生一些非常难以发现的错误。