-1

几天来我一直在为此挠头,但我仍然无处可去。我正在尝试通过 PHP PDO 从 MySQL 数据库中提取一小组值;我知道 PDO 的工作原理是我在其他地方使用它时的工作原理,并且我的代码基于以前工作的代码。

function custom_sub_cat_list($db_details, $cat_id) { //ln21
$subcat = NULL;
try {
    $h = new PDO("mysql:host=".$db_details['host'].";dbase=".$db_details['db'],$db_details['user'],$db_details['pass']);
    $h->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch(PDOException $ex) {
    return false;
}
try {
    $q = $h->prepare("SELECT category FROM :tbl WHERE parentid = :catid;");
    $q->bindValue(":tbl", $db_details['tbl'], PDO::PARAM_STR);
    $q->bindValue(':catid', $cat_id, PDO::PARAM_STR);
    $q->execute();
    while($row = $_query->fetch()) {
        $subcat['id'][] = $row['categoryid'];
        $subcat['name'][] = $row['category'];
    };
    return $subcat;
} catch(PDOException $ex) {
    return false;
}
}//ln49

我在 bindValue 上得到“调用非对象上的成员函数 bindValue()”,并被如下调用。

$cat_id     = 123;
$db_details = array(
    "host"  => $sql_host,
    "db"    => $sql_db,
    "user"  => $sql_user,
    "pass"  => $sql_password,
    "tbl"   => $sql_tbl['categories']
);
custom_sub_cat_list ($db_details, $cat_id)

我确信这是非常明显的事情,但我看不到问题所在,我想要一双新的眼睛。

以下工作版本

非常非常感谢你!对于所有帮助过的人,我也学到了一些东西 :-) 那里有一些我忽略的愚蠢错误,我只是责怪看了两天扎实的东西。

function custom_sub_cat_list($db_details, $cat_id) {
$subcat = NULL;
try {
    $h = new PDO("mysql:host=".$db_details['host'].";dbname=".$db_details['db'].";charset=utf8",$db_details['user'],$db_details['pass']);
    $h->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $h->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $q = $h->prepare("SELECT category, categoryid FROM ".$db_details['table']." WHERE parentid = :cid;");
    $q->bindParam(':cid', $cat_id, PDO::PARAM_INT);
    $q->execute();
    while($row = $q->fetch()) {
        $subcat['id'][] = $row['categoryid'];
        $subcat['name'][] = $row['category'];
    };
    $h = NULL;
    return $subcat;
} catch(PDOException $ex) {
    print_r($ex->getMessage());
    print_r($ex->getTrace());
    //return false;
}
}
4

3 回答 3

1

你不需要一双新鲜的眼睛

您不是画家,而是程序员(据说)。
因此,您不必查看您的代码,而是必须运行它。并启用错误报告。

哦,刚刚发现它
当然,你不应该堵嘴错误信息!

} catch(PDOException $ex) {
    return false;
}

@ 运算符的现代版本。
请摆脱代码中的所有块,并在了解它们的用途try..catch后才开始使用它们。

所以,为了解决这个问题以及未来的许多其他问题

  1. 摆脱代码中的所有 try..catch 块。
  2. 启用 PDO 的错误报告,如我在评论中链接到的标签 wiki 中所述。
  3. 不要对标识符使用占位符,而是按照我链接到的标签 wiki 中的描述格式化它们
  4. display_errors如果您不想显示错误,请关闭设置(我能想到的抑制错误消息的唯一原因)。

此外,您不应在每个函数调用中打开单独的连接。
在脚本的开头创建一个连接,然后在函数中使用 if,使用

global $h;
于 2013-03-08T15:24:46.173 回答
0
$q = $h->prepare("SELECT category FROM :tbl WHERE parentid = :catid;");

您不能在 SQL 中对表名使用绑定参数。

当您尝试像这样准备无效的 SQL 语句时,prepare() 返回false,而不是 PDOStatement 对象。

$q->bindValue(":tbl", $db_details['tbl'], PDO::PARAM_STR);

然后你尝试在 $q 上调用 bindValue() 方法,但是标量值false没有方法,所以这是一个致命错误。

您还试图捕获异常,但您没有将 PDO 配置为在出错时引发异常。所以 PDO 函数默认只通过返回来报告错误false

正如@Arkh 所示,您需要告诉 PDO 抛出异常:

$h->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
于 2013-03-08T15:52:47.980 回答
-1

因此,您的错误告诉您 $q 不是对象。这意味着$h->prepare("SELECT category FROM :tbl WHERE parentid = :catid;");失败了。

阅读PDO::prepare文档时,您可以阅读以下内容:

返回值

如果数据库服务器成功准备语句,PDO::prepare() 返回一个 PDOStatement 对象。如果数据库服务器无法成功准备语句,则 PDO::prepare() 返回 FALSE 或发出 PDOException(取决于错误处理)。

由于您尚未设置 PDO 以引发异常,因此您应该这样做以获得良好的错误消息或检查 $q 的值并获取最后报告的错误。第一种方法:

function custom_sub_cat_list($db_details, $cat_id) { //ln21
$subcat = NULL;
try {
    $h = new PDO("mysql:host=".$db_details['host'].";dbase=".$db_details['db'],$db_details['user'],$db_details['pass']);
    $h->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $h->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $q = $h->prepare("SELECT category FROM :tbl WHERE parentid = :catid;");
    $q->bindValue(":tbl", $db_details['tbl'], PDO::PARAM_STR);
    $q->bindValue(':catid', $cat_id, PDO::PARAM_STR);
    $q->execute();
    while($row = $_query->fetch()) {
        $subcat['id'][] = $row['categoryid'];
        $subcat['name'][] = $row['category'];
    };
    return $subcat;
} catch(PDOException $ex) {
    echo $ex->getMessage();
    return false;
}
}//ln49

这给出了错误:

SQLSTATE[42000]:语法错误或访问冲突:1064 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获取在 '? 附近使用的正确语法。哪里父母=?在第 1 行

第二种方法:

function custom_sub_cat_list($db_details, $cat_id) { //ln21
$subcat = NULL;
    $h = new PDO("mysql:host=".$db_details['host'].";dbase=".$db_details['db'],$db_details['user'],$db_details['pass']);
    $h->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $q = $h->prepare("SELECT category FROM :tbl WHERE parentid = :catid;");
    if ($q === false) {
        print_r($h->errorInfo());
        return false;
    }
    $q->bindValue(":tbl", $db_details['tbl'], PDO::PARAM_STR);
    $q->bindValue(':catid', $cat_id, PDO::PARAM_STR);
    $q->execute();
    while($row = $_query->fetch()) {
        $subcat['id'][] = $row['categoryid'];
        $subcat['name'][] = $row['category'];
    };
    return $subcat;
}//ln49

结果:

Array ( [0] => 42000 1 => 1064 [2] => 您的 SQL 语法有错误;请查看与您的 MySQL 服务器版本相对应的手册,以了解在 '? WHERE parentid = ?' 附近使用的正确语法在第 1 行)

您的问题是您不能为 :tbl (或 SQL 字符串的其他非值部分)使用绑定值。所以你必须这样做:

$q = $h->prepare("SELECT category FROM ".$db_details['tbl']." WHERE parentid = :catid;");
于 2013-03-08T15:45:24.947 回答