SQL文を書く知識はあるので、そのままSQLを書いてしまえばよいのですが、CakePHPを活用する上でモデルのルールに従った記述方法を知っておくことも重要です。
そこで、この記事では「このSQL文はCakePHPではどのように実装するんだっけ?」となった場面で役に立つようなメモを書き溜めていきたいと思います。
ちなみに、これらの動作はMySQL5.1、CakePHP1.3.9で確認済みです。
limit句でselect結果を絞り込む
SQLではlimit句を用いる事で、select結果の数を絞り込む事ができます。例えば、以下のようにオフセットを5、データ数を3とした場合、条件に合うデータの6番目から3つのレコードを取得できます。(オフセットは0が1番目を示すため)
SELECT * FROM SAMPLE LIMIT 5, 3 ;
これをCakePHPでは以下のように記述します。
$res = $this->Sample->find('all', array( 'offset' => 5, 'limit' => 3, ));
MySQLの比較演算子を使う
例えば特定のカラム「name」に文字列「hoge」が入っているレコードを抽出する場合、CakePHPでは以下のように書きます。
$res = $this->Sample->find('all', array( 'conditions' => array('Sample.name' => 'hoge'), ));
逆に「hoge」が入っていないレコードを抽出する場合は以下のように書きます。
$res = $this->Sample->find('all', array( 'conditions' => array('Sample.name <>' => 'hoge'), ));
MySQLの仕様に従い「<=>」「>=」「!=」などの比較演算子も同じようにして利用可能です。
条件でIN句を使う
例えば以下のように複数の値を条件とするIN句があります。
SELECT * FROM SAMPLE WHERE color IN ('blue', 'yellow', 'red') ;
この場合、CakePHPのモデルでは「conditions」にarrayで値を指定すればよいです。
$res = $this->Sample->find('all', array( 'conditions' => array('Sample.color' => array('blue', 'yellow', 'red')), ));
条件でワイルドカードを使う
LIKE句などでワールドカード「%」を使い、文末に「tmp」のあるレコードを抽出する場合は以下のようにします。
$res = $this->Sample->find('all', array( 'conditions' => array('Sample.name LIKE' => '%tmp'), ));
もちろん一文字マッチのアンダーバー「_」も同様に使うことができます。
$res = $this->Sample->find('all', array( 'conditions' => array('Sample.name LIKE' => '_tmp'), ));
ちなみに「%」という文字で検索したい場合、MySQLのルールに従いエスケープします。
$res = $this->Sample->find('all', array( 'conditions' => array('Sample.name LIKE' => '\%tmp'), ));
条件でBETWEEN句を使う
例えば、任意のカラムが整数の1000から2000までのレコードを抽出する場合、SQLでは以下のように書きます。
SELECT * FROM SAMPLE WHERE price BETWEEN 1000 AND 2000 ;
これをCakePHPでは以下のように書きます。
$res = $this->Sample->find('all', array( 'conditions' => array('Sample.price BETWEEN ? AND ?' => array(1000, 2000)), ));
MySQLのキャスト関数を使う
例えば、文字型のカラム「price」を整数として比較対象にする場合、以下のようにして型変換できます。
$res = $this->Sample->find('all', array( 'conditions' => array('cast(Sample.price as signed)' => 500), ));
MySQLの仕様に従い、signed以外でもbinary、char、date、timeなどの型にも変換可能です。
2012/5/16更新