CakePHPのModelを使う

CakePHPのModelを使う
データベース関連処理をシンプルに解決
2007年3月28日 安藤祐介
Copyright © YusukeAndo. 2007. All rights reserved.
1
アジェンダ
CakePHPのおさらい
データベース抽象化レイヤ機能
クエリ実行機能
validation
アソシエーション
まとめ
Copyright © YusukeAndo. 2007. All rights reserved.
2
CakePHPのおさらい
Copyright © YusukeAndo. 2007. All rights reserved.
3
状況
Scaffolding機能等を持つRoR世代のフレームワーク
環境に依存しないで動作する (PHP4/5)
外部ライブラリなどを必要としないフルスタックなフレー
ムワーク
とにかく簡単に利用可能かつ拡張性も十分
→日本国内での利用も拡大中
Copyright © YusukeAndo. 2007. All rights reserved.
4
Googleのトレンド情報
直近のデータの絞込みが出来るように
→日本語での検索トレンド2位(2007/3現在)
Copyright © YusukeAndo. 2007. All rights reserved.
5
コードのイメージ
app/models/memo.php
class Memo extends AppModel {
var $name = 'Memo';
var $belongsTo = array('User');
}
リレーション指定
app/models/user.php
class User extends AppModel {
var $name = 'User';
var $validate = array(
'login_id' => '/^[a-zA-Z0-9]*$/',
'password' => '/^[a-zA-Z0-9]*$/',
'name' => VALID_NOT_EMPTY,
);
}
Copyright © YusukeAndo. 2007. All rights reserved.
6
コードのイメージ
app/controllers/memos_controller.php
class MemosController extends AppController {
var $scaffold;
var $name = 'Memos';
Scaffoldの利用
クラス名の指定
function index()
{
//表示データを取得
$data = $this->Memo->findAll(null,null,'Memo.id DESC');
$this->set('data',$data);
}
}
Copyright © YusukeAndo. 2007. All rights reserved.
7
実行例
→少ないコード量でWEBアプリが作成可能
Copyright © YusukeAndo. 2007. All rights reserved.
8
データベース抽象化レイヤ機能
Copyright © YusukeAndo. 2007. All rights reserved.
9
データベースの抽象化
データベースの種類を問わない実装を提供
PEAR::DBやPDOなどが広く認知
パラメータを元に各DB用の処理を内部で判別
CakePHPはライブラリを必要とせずに抽象化を実現
CakePHPは app/config/database.php 内の設定によ
り下記のデータベースを利用可能
mysql postgres sqlite adodb pear mssql odbc
→主要なデータベースをカバーし、PEAR、ADOdb等も利用可能
Copyright © YusukeAndo. 2007. All rights reserved.
10
データベース設定の記述例
app/config/database.php
class DATABASE_CONFIG
{
var $default = array('driver' => 'mysql',
'connect' => 'mysql_connect',
※利用するドライバ
永続接続など
'host' => 'localhost',
'login' => 'dbuser',
接続先設定
'password' => 'hoge',
'database' => 'beefcurry',
'prefix' => '');
var $test = array('driver' => 'mysql',
'connect' => 'mysql_connect',....
テーブル名の接頭語
複数の設定を記述可
}
※ PEARを利用する場合は pear-mysql のように記述
Copyright © YusukeAndo. 2007. All rights reserved.
11
複数のデータソースのサポート
複数のデータソースが必要な状況
複数のデータベースを同時扱う場合
運用時と開発時で接続先を切り替える場合
検索機能などで参照用データベースへ接続する場合
→上記の様な場合はdatabase.php内に複数の設定を記述して
おく事で設定ファイルの都度書換えなどをせずに対応可能
(特に指定しない場合は $default が使用される。)
Copyright © YusukeAndo. 2007. All rights reserved.
12
Modelの使用する設定の指定
app/models/memo.php (モデル毎に指定する場合)
class Memo extends AppModel {
var $name = 'Memo';
var $belongsTo = array('User');
var $useDbConfig = ‘test’;
使用する設定の名称
}
app/app_model.php (アプリ全体に適用する場合)
class AppModel extends Model{
function __construct() {
if (DEBUG > 0) {
$this->useDbConfig = "test";
}
parent::__construct();
}
}
Copyright © YusukeAndo. 2007. All rights reserved.
デバッグモードであれば
開発用DBへ接続
13
クエリ実行機能
Copyright © YusukeAndo. 2007. All rights reserved.
14
CakePHPが提供するクエリ実行機能
Modelを通じて下記の処理が可能
対象テーブル・主キーの指定
データ構造を元にした登録・更新クエリの自動実行
条件を元にした検索クエリの自動実行
任意のSQLの実行
→scaffoldを利用する場合などは上記の機能を意識する必要は
ないが、コードの実装を行う場合は非常に有用な機能。都合が
悪い場合はSQLの任意実行する従来の方法も可能。
Copyright © YusukeAndo. 2007. All rights reserved.
15
対象テーブル・主キーの指定
モデル名を元に自動でテーブルを決定
例) モデル名:Book 対象テーブル:books
idという名称のカラムを主キーとして認識
上記のルール外のテーブル、主キーを指定したい場合は
モデルのプロパティに設定を行う
対象テーブルにNULLを指定する事でDBを使用しないモ
デルとする事も可能
→既存のスキーマやルールの上でCakeを使う場合の必須知識
Copyright © YusukeAndo. 2007. All rights reserved.
16
対象テーブル・主キーの指定例
app/models/user.php
class User extends AppModel {
var $name = ‘User';
var $useTable = ‘user_account’;
var $primaryKey = ‘login_id’;
使用するテーブル名
主キーのカラム名
var $validate = array(
'login_id' => '/^[a-zA-Z0-9]*$/',
'password' => '/^[a-zA-Z0-9]*$/',
'name' => VALID_NOT_EMPTY,
);
}
→暗黙的なルールに従うよりも把握しやすい場合も
Copyright © YusukeAndo. 2007. All rights reserved.
17
登録・更新クエリの自動実行
配列化したパラメータを元に自動でクエリを実行
idという名称のカラムを主キーとして認識
主キーを指定し、該当レコードが存在すれば更新
単一カラムの更新であれば直接指定も可能
→INSERT UPDATEなどのSQLを整形する必要が無くなる
Copyright © YusukeAndo. 2007. All rights reserved.
18
登録・更新クエリの自動実行例(配列版)
app/controllers/memos_controller.php
class MemosController extends AppController {
function hoge(){
$data['Memo'] = array(
'kind_cd' => '2',
カラム名をキーにした
'user_id' => '2',
ハッシュを渡す
'contents' => 'モデルから登録'
);
$this->Memo->save($data);
$this->flash('hoge','/memos/');
テスト用の表示
}
}
→INSERT UPDATEなどのSQLを整形する必要が無くなる
(渡すデータに存在する主キーの指定を含めればUPDATE)
Copyright © YusukeAndo. 2007. All rights reserved.
19
登録・更新クエリの自動実行例(配列版)
SQLデバッグ表示で確認
→タイムスタンプなどは自動で補完して実行
Copyright © YusukeAndo. 2007. All rights reserved.
20
更新クエリの自動実行例(単一カラム版)
app/controllers/memos_controller.php
class MemosController extends AppController {
function hoge2(){
対象のレコードを指定
$this->Memo->id = 4;
$this->Memo->saveField('contents','部分更新');
$this->flash('hoge2','/memos/');
}
}
→モデルのプロパティに対象レコードのIdを指定する
Copyright © YusukeAndo. 2007. All rights reserved.
21
更新クエリの自動実行例(単一カラム版)
SQLデバッグ表示で確認
→ステータスの更新などに便利
Copyright © YusukeAndo. 2007. All rights reserved.
22
検索クエリの自動実行
配列化したパラメータを元に自動でクエリを実行
取得対象カラム、ORDER LIMITなどが指定可能
自力で構築したWHERE句の指定も可能
マジックメソッドでの検索も可能 findBy{カラム名}
全ての引数には初期値あり
function findAll($conditions = null, $fields = null,
$order = null, $limit = null, $page = 1, $recursive =
null)
Copyright © YusukeAndo. 2007. All rights reserved.
23
検索クエリの自動実行 (find findAll)
app/controllers/memos_controller.php
class MemosController extends AppController {
function hoge3(){
検索パラメータ
$cond = array(
‘Memo.kind_cd’ => ‘2’, // kind_cd = ‘2’ に展開される
‘Memo.created’ => ‘>= 2007-01-01‘ // >= での比較になる
);
今回は条件のみ指定
$data = $this->Memo->findAll($cond);
$this->flash('hoge3','/memos/');
}
}
Copyright © YusukeAndo. 2007. All rights reserved.
24
検索クエリの自動実行
SQLデバッグ表示で確認
= の比較
>= の比較
→パラメータを元にWHERE句を生成して実行
Copyright © YusukeAndo. 2007. All rights reserved.
25
検索クエリの自動実行 (OR検索)
app/controllers/memos_controller.php
class MemosController extends AppController {
function hoge4(){
$cond['OR'] = array(
'Memo.kind_cd' => '2',
'Memo.created' => '>= 2007-01-01'
);
$data = $this->Memo->findAll($cond);
$this->flash('hoge4','/memos/');
}
}
Copyright © YusukeAndo. 2007. All rights reserved.
26
検索クエリの自動実行(OR検索)
SQLデバッグ表示で確認
→OR検索も可能。(IN LIKE も可能)
Copyright © YusukeAndo. 2007. All rights reserved.
27
検索時の注意点
比較演算子の指定方法はどうすれば?
値の前に演算子を置き、スペースを空ける。
省略時は = として比較する句を生成
値が配列の場合は IN (n,n,n) に展開
入力値を値に使う場合は = であっても明示的に指定す
る。
→演算子をインジェクションされないように注意。
Copyright © YusukeAndo. 2007. All rights reserved.
28
入力値との組み合わせ例
app/controllers/memos_controller.php
class MemosController extends AppController {
function moge(){
$param = $this->data['Memo']['kind_cd'];
$cond = array(
'kind_cd' => '= '.$param
);
$this->Memo->findAll($cond);
}
}
→入力値に比較演算子などが入るので=での比較を指定
Copyright © YusukeAndo. 2007. All rights reserved.
29
入力値との組み合わせ例
SQLデバッグ表示で確認
値として処理
→危険な入力値が入っても適切に処理されている
Copyright © YusukeAndo. 2007. All rights reserved.
30
任意のSQLの実行
app/controllers/memos_controller.php
class MemosController extends AppController {
function hoge5(){
$sql = “SELECT * FROM memos”;
$data = $this->Memo->query($sql);
$this->flash('hoge5','/memos/');
}
function hoge6(){
$cond = "kind_cd > 4";
$order = "id DESC";
$data = $this->Memo->findAll($cond,NULL,$order);
$this->flash('hoge6','/memos/');
}
}
Copyright © YusukeAndo. 2007. All rights reserved.
31
validation
Copyright © YusukeAndo. 2007. All rights reserved.
32
validation機能
validation機能の概要
Model内に各カラムの制限値を正規表現で設定
save()メソッド実行時に自動で検査し通過時のみデータを
登録する。
validatesメソッドで任意に実行も可能。
独自の検証ロジックが必要な際はModelのvalidatesをオー
バーライドして実装する。
エラーの状況を画面出力などに必要な場合は
validateErrorsメソッドを利用。
→scaffoldではこれらの機能がフル活用されている。
Copyright © YusukeAndo. 2007. All rights reserved.
33
Validation設定例
app/models/user.php
class User extends AppModel {
var $name = ‘User';
var $useTable = ‘user_account’;
var $primaryKey = ‘login_id’;
var $validate = array(
'login_id' => '/^[a-zA-Z0-9]*$/',
'password' => '/^[a-zA-Z0-9]*$/',
各カラムへの設定
'name' => VALID_NOT_EMPTY,
);
}
→空欄、数値、メールなどについては定数が利用可能
Copyright © YusukeAndo. 2007. All rights reserved.
34
Validation設定例
app/controllers/users_controller.php
<?php
class UsersController extends AppController {
function fuga(){
$data['User'] = array(
'login_id' => '+*+*+*+*',
'password' => 'abcde',
'name' => ''
);
if ($this->User->validates($data)) {
$this->User->save($data);
} else {
$this->validateErrors($this->User);
}
}
}
Copyright © YusukeAndo. 2007. All rights reserved.
不正を含むデータ
適合していれば保存
エラー項目の取得
35
Validation設定例
app/views/users/fuga.thtml
<?php echo $html->tagErrorMsg('User/login_id', 'ログインIDが正しくありません。')?>
<?php echo $html->tagErrorMsg('User/password', 'パスワードが正しくありません。')?>
<?php echo $html->tagErrorMsg('User/name', '名前が正しくありません。')?>
→tagErrorMsgで該当モデルの該当項目にエラーがあった場合
の表示を定義可能
Copyright © YusukeAndo. 2007. All rights reserved.
36
Validation設定例
→SQLは実行されず、エラー項目がViewへ通知されている。
Copyright © YusukeAndo. 2007. All rights reserved.
37
アソシエーション
Copyright © YusukeAndo. 2007. All rights reserved.
38
アソシエーション機能
Model内で従属関係を指定する。
belongsTo hasMany hasOne hasAndBelongsToMany な
どを指定可能
外部キーが命名規則に当てはまらない場合はキー名も併せ
て指定する
上記の設定がなされていればfindAllなどの際に従属テーブ
ルをJOINするSQLが実行される。
findAllなどのrecursive引数により関連レコードの取得深度
を設定可
→基本的にModelに対して設定をするだけでOK
Copyright © YusukeAndo. 2007. All rights reserved.
39
アソシエーション設定の例
app/models/memo.php
class Memo extends AppModel {
var $name = 'Memo';
var $useDbConfig = ‘test’;
//var $belongsTo = array('User');
リレーション簡易設定
var $belongsTo = array('User' =>
array('className' => 'User',
'conditions' => '',
リレーション設定
(冗長な記述)
'order' => '',
'foreignKey' => 'user_id'
));
}
→冗長な設定をする場合はbake.phpなどを利用すると良い
Copyright © YusukeAndo. 2007. All rights reserved.
40
検索クエリの自動実行(アソシエーション時)
Copyright © YusukeAndo. 2007. All rights reserved.
41
まとめ
Modelの機能を活用する事でDB処理を大幅にカット可能
汎用性に配慮した実装になっている
状況次第で従来どおりのクエリ処理を記述してもOK
アソシエーションなどの設定はツールを活用した方が良い
実感としてはかなり楽です。(クエリの整形とか)
利用のインターフェースが複数用意されているので、違和
感のない利用方法が見つけられると思います。
Copyright © YusukeAndo. 2007. All rights reserved.
42
謝辞
参考サイト
CakePHPのおいしい食べ方
http://cakephp.seesaa.net/
Copyright © YusukeAndo. 2007. All rights reserved.
43
質疑応答 ご静聴ありがとうございました。
Copyright © YusukeAndo. 2007. All rights reserved.
44