0

キーと値のバインドを使用して SQL ステートメントを作成および実行するために、次の関数を作成しました。bindValue() を使用して、キーと値のペアの配列を SQL 文字列内の対応する識別子にバインドしています。(echo ステートメントはデバッグ用です)。

public function executeSelect($sql, $bindings = FALSE)
{
    $stmt = $this->dbPDO->prepare($sql);

    if ($bindings)
    {
        foreach($bindings as $key => $value)
        {
            $success = $stmt->bindValue($key, $value);
            echo "success = $success, key = $key, value = $value<br />";
            if (!$success)
            {
                throw new Exception("Binding failed for (key = $key) & (value = $value)");
            }
        }
    }

    echo "Beginning execution<br />";
    if ($stmt->execute())
    {
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    else
    {
        return FALSE;   
    }
}

この関数への入力は次のとおりです。

$stmt = "SELECT * FROM test WHERE id = :id";
$bindings = array(":id" => "3", ":Foo" => "Bar");

$bindings 配列の 2 番目のループでは、$success が false と評価されると予想し、入力 SQL に " " が存在しないため "Bar" を " :Foo"にバインドできないため、カスタム例外をスローします。:Foo

代わりに、$success は $bindings 配列の両方のキーと値のペアに対して true (1) と評価され、->execute() によって PDOException がスローされます。"(HY000)SQLSTATE[HY000]: General error: 25 bind or column index out of range"

bindValue が false を返さないのはなぜですか?

4

1 に答える 1

1

このように機能するからです。
バインド時ではなく実行時にエラーをスローします。それで全部です。

したがって、ループする必要はなく、メソッドをより短くすることができます。

public function executeSelect($sql, $bindings = FALSE)
{
    $stmt = $this->dbPDO->prepare($sql);
    $stmt->execute($bindings);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

実行結果を確認する必要もないと思います。
エラーの場合、すでに例外が発生します。

ところで、これに基づいていくつかのヘルパー関数を作成し、スカラー値と単一行を返します。彼らは非常に役に立ちます。名前付きのプレースホルダーは少し退屈だと思いますが。このコードを比較してください:

$name = $db->getOne("SELECT name FROM users WHERE group=?i AND id=?i",$group,$id);
vs.
$sql = "SELECT name FROM users WHERE group=:group AND id=:id";
$name = $db->getOne($sql,array('group' => $group, 'id' => $id));

名前付きは、匿名の 2 倍のコードを必要とします。
頭字語の完璧な例WET- 「Write Everything Twice」

于 2013-02-02T05:53:58.460 に答える