忍者ブログ
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。



2024/03/19 17:21 |
CakePHP-05:CakePHPで任意のSQLを実行する

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
<?php
    
    /*
        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
<?php
    
    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
<?php
    
    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の記事一覧
PR


2009/11/02 22:48 | Comments(0) | TrackBack() | PHP

トラックバック

トラックバックURL:

コメント

コメントを投稿する






Vodafone絵文字 i-mode絵文字 Ezweb絵文字 (絵文字)



<<そしてSteins; Gateは神となった―――ゲームレビュー:シュタインズゲート | HOME | 買った本リスト 2009/11/01>>
忍者ブログ[PR]