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
© Copyright 2024 Paperzz