cakephperの日記(CakePHP, Laravel, PHP) Twitter


継続的WebセキュリティテストサービスVAddyを始めました!

2012-02-04

CakePHP2 独自SQL文でPrepared Statementを使う

CakePHP1系では、

Model->query('select * from posts where id=?', array('hoge'));

みたいにして擬似バインドできましたが、CakePHP2からは下記の方法でやるとPrepared StatementでSQLを発行してくれます。

// in controller
$result = $this->Post->getDatasource()->fetchAll(
    'select * from posts as Post where Post.id = ? or Post.id = ?', 
    array(1, "abc")
);

$result = $this->Post->getDatasource()->fetchAll(
    'select * from posts as Post where Post.id = :id or Post.id = :id2', 
    array('id'=>1, 'id2' => 2)
);

詳細は下記に。

http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#prepared-statements


[追記] 2013/1/29

CakePHP2.1を確認したところ、Model::query()のものは、すべてfetchAll()に渡されるため、擬似バインドではなく、Prepared Statementになってました。

よかった。

Model::query()を使ったほうが記述が楽なので、そっちを使っていれば良いですね。


[追記] 2013/1/28

デフォルトだとキャッシュが効いてしまうので、第3引数にarray('cache' => false)を渡せばキャッシュ無効にできます

http://api.cakephp.org/class/dbo-source#method-DboSourcefetchAll

// in controller
$result = $this->Post->getDatasource()->fetchAll(
    'select * from posts as Post where Post.id = ? or Post.id = ?', 
    array(1, "abc"),
    array('cache' => false)
);

ここで言っているキャッシュとは、1回のアクセスの中でのみ利用されるため、1アクセスで同じクエリが複数回実行されるものに限り有効になります。


[追記]

Prepared Statementsでバインドした値が、sql_debug画面に出なかったのでパッチ書いて送りました。

CakePHP2.1ブランチで取り込まれました

https://github.com/cakephp/cakephp/commit/e8a9d93eb52cdff15acee789a89e3c569da9b259

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証