fuelPHPのDBの扱い。
SQL文書くのが何か好きなのでDB::queryでSQL文をそのまま打ってます。
ですが、これだとエスケープ機能が働かず、SQLインジェクションという攻撃を受ける可能性があるとのこと。
fuelPHPではQuery Builderという機能が備わっていてこちらを使うと自動でエスケープが働き、この機能自体にバグがなければSQLインジェクションは受けないとのこと。
セキュリティ的には楽が出来るので使いたいところなのですが・・・研修でも普通のSQL文しか使ってない身としてはこのQuery Builderが使いにくくてしょうがないのです。
例えば
$str = DB::query( "select * from dummy where name = 'stickpan'" )
->execute()
->as_array();
で$strにSQLを実行して、その内容を格納出来るという書き方があります。
これをQuery Builderで同じことをすると
$str = DB::select()
->from( 'dummy' )
->where( 'name' , 'stickpan')
->execute()
->as_array();
こんな感じになります。
これぐらい単純なものだったらいくらでも書き直せますが、実際に使うSQL文はこんな簡単なのを使う方が少ないわけで・・・
通常の複雑なSQLをQuery Builderを使って再現しようとするとこれが非常にめんどくさいのです。だからDB::query()ばっかり使ってたのですが・・・SQLインジェクションの話を先輩から聞いてどうもそうはいかなくなりました。
そしてまず面倒に思ったことがupdateを使用する時。
$query = DB::query( "update dummy set count = count + 1 where name = 'stickpan'" )
->execute();
countという数値を入れるフィールドに+1したい時、通常のSQL文ならこれだけで済みます。
しかし、Query Builderのupdateを使う場合だと
$query = DB::update( 'dummy' )
->set( array( 'count' => ○○+1 ) )
->where( 'name' , 'stickpan' )
->execute();
○○の部分が厄介なところ。
生SQL的には'count'って入れたい所ですが、=>のあとに入るのは代入する値になります。
なのでcountという文字列に+1という謎の計算をしちゃうことになります。
1つのupdate内だけで済ませたかったのですが○○の部分に今'count'に入っている数値を入れるとなると、この'count'を取り出すために別のSQL文が必要になってしまいます。
なので・・・
$query_count = DB::select()
->from( 'dummy' )
->where( 'name' , 'stickpan' )
->execute()
->as_array();
$query = DB::update( 'dummy' )
->set( array( 'count' => $query_count[0]['count']+1 ) )
->where( 'name' , 'stickpan' )
->execute();
こんな書き方になっちゃう気がします。
元々1つで済むSQL文が二つになったりして面倒なのです・・・何かいい方法はないものか。