2013-01-29

PDOのプリペアドステートメントで同じ名前のパラメータマーカは使えない

PDOでプリペアドステートメントを使うとき、クエリ中にパラメータマーカを指定するが、このとき、同じ名前のパラメータマーカは使えない。
でも、使ってもエラーにならない。

クエリの結果を精査すれば、クエリで想定した結果にならないためわかるのだが、テストが嫌いな俺は、クエリそのものを検査することにした。

//  すべてのパラメータマーカを取得する。
preg_match_all('/(:[\w]+)/', $sql, $matches);

//  パラメータマーカの出現回数を得る。
$param = array_count_values($matches[1]);

//  2回以上出現したパラメータマーカを調べる。
foreach($param as $key => $val) {
  if($val > 1) {
    echo "パラメータマーカ {$key} を {$val} 個検出しました。";
    //  ここでエラーを発生させるか、強制終了する。
  }
}

こんな感じのロジックをPDOを継承したクラスに仕込んでおけばOK。

class dao extends PDO
{
    const DAO_ERROR_PARAMETER_MARKER_DUPLICATED = 777;

    //  今回必要なところだけ記述
    public function prepare($statement, $options = array())
    {
        preg_match_all('/(:[\w]+)/', $sql, $matches);
        $param = array_count_values($matches[1]);
        foreach($param as $key => $val) {
            if($val > 1) {
                //  エラーモードに応じて、例外を発生させるか、falseを返す。
                $err_mode = $this->getAttribute(PDO::ATTR_ERRMODE);
                if($err_mode === PDO::ERRMODE_EXCEPTION) {
                    throw new Exception("パラメータマーカ {$key} を {$val} 個検出しました。"
                                      , self::DAO_ERROR_PARAMETER_MARKER_DUPLICATED);
                }
                else {
                    return false;
                }
            }
        }
        return parent::prepare($statement, $options);
    }
}

0 件のコメント:

コメントを投稿

Chatの「メッセージは投稿者によって削除されました」を非表示にする方法

Chrome拡張機能を自作してやってみよう! ♪できるかな できるかな ・・・ 無理ぽ (´・ω・`) iframeの中に、実際のメッセージのやり取りが表示されるので、 $(function(){ $('iframe[name^="spa...