cakePHPのDBアクセスは、基本的にはモデル作って関係を記述してコントローラからfindするだけで自動的に行ってくれます。
が、これだと常に全フィールドをそのまま持っくることしかできません。
"MIN(books.id)"が欲しい、といった場合はfind内に記述することで実現できます。
$this->Book->find('all',array('fields'=>'MIN(Book.id) AS hoge'));
が、"books.created + INTERVAL 1 HOUR"が欲しいんだよ、とばかりに
$this->Book->find('all',array('fields'=>'Book.created + INTERVAL 1 HOUR AS hoge'));
とか書くとSQLエラーになります。
SQL的には何故か勝手に"SELECT `Book`.`created + INTERVAL 1 HOUR` AS `hoge`"と変形されていました。
こういう場合のためにqueryメソッドで直接SQLを書くことが出来ます。
$this->Book->query('SELECT Book.created + INTERVAL 1 HOUR AS hoge FROM books AS Book');
それはまあいいのですが、実はモデルに対して知らないメソッドが来るとそのままSQLに渡されます。
$this->Book->{'SELECT Book.created + INTERVAL 1 HOUR AS hoge FROM books AS Book'}();
両者の結果は同じになります。
あんまり意味がないというか意味がわからない機能だ。
こんな書き方しかできないのかといえばそうでもなく、イレギュラーなSQLは基本的にモデルに追いやります。
これでコントローラからモデルに依存するコードを排除することができます。
/app/controllers/book_controller.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/*
Bookコントローラ
*/
class BookController extends AppController{
//自分の名前
var $name = 'Book';
//Book/indexAction
public function index($id=false) {
//任意のSQLを実行
$this->set('books', $this->Book->getAfter1Hour($id));
}
}
|
実装自体はモデルで地道にSQLを書きます。
本当はこんな書き方ではなく正しい方法があるのかもしれませんが、よくわかりませんでした。
app/models/book.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class Book extends AppModel {
//自分の名前
var $name = 'Book';
//Book::getAfter1Hour
public function getAfter1Hour($books_id=false){
//SQL
$sql=" SELECT books.created + INTERVAL 1 HOUR AS hoge FROM books";
if($books_id){
App::import('Sanitize');
$sql.=" WHERE books.id = '".Sanitize::escape($books_id)."'";
}
//実行
return $this->query($sql);
}
}
|
作成したメソッドを呼び出せば任意のSQLを実行することが出来ます。
また、queryメソッドの第二引数に配列を与えるとバインドしてくれます。
app/models/book.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class Book extends AppModel {
//自分の名前
var $name = 'Book';
//Book::getAfter1Hour
public function getAfter1Hour($books_id=false){
//SQL
$sql=" SELECT books.created + INTERVAL 1 HOUR AS hoge FROM books";
if($books_id){
$sql.=' WHERE books.id = ?';
}
//実行
return $this->query($sql,array($books_id));
}
}
|
http://localhost/Book/index/1'%20OR%201=1
↑というふうに引数を渡すと、SQLは↓というふうにになります。
SELECT books.created + INTERVAL 1 HOUR AS hoge FROM books WHERE books.id = '1\' OR 1=1'
CakePHPの記事一覧