-1

私はこれについて数日間頭を悩ませてきましたが、まだどこにも行きません. PHP PDO を介して MySQL データベースから値の小さなセットを取得しようとしています。私は PDO を他の場所で使用しているため、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. コメントでリンクしたタグ wiki で説明されているように、PDO のエラー レポートを有効にします。
  3. 識別子にプレースホルダーを使用せず、リンク先のタグ wiki に記載されているようにフォーマットします。
  4. display_errorsエラーを表示したくない場合は、設定をオフにします (エラー メッセージを非表示にする唯一の理由は思いつきます)。

また、すべての関数呼び出しで個別の接続を開くべきではありません。
スクリプトの先頭で 1 つの接続を作成し、関数内で if を使用します。

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

SQL のテーブル名にバインドされたパラメーターを使用することはできません。

このような無効な SQL ステートメントを準備しようとすると、prepare() はfalsePDOStatement オブジェクトではなく を返します。

$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 doc を読むときは、次のように読むことができます。

戻り値

データベース サーバーがステートメントの準備に成功すると、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 構文にエラーがあります。near '? を使用する正しい構文については、MySQL サーバーのバージョンに対応するマニュアルを確認してください。WHERE 親 ID = ?' 1行目

2 番目の方法:

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 構文にエラーがあります。near '? WHERE parentid = ?' を使用する正しい構文については、MySQL サーバーのバージョンに対応するマニュアルを確認してください。 1行目)

問題は、:tbl (または SQL 文字列の他の非値部分) にバインドされた値を使用できないことです。だからあなたはこれをしなければなりません:

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