Posts tagged model
CakePHP1.2 モデルの generateList は非推奨メソッドなので find(’list’) を使用する
3CakePHP で select タグを作成する際に CakePHP1.1 ではモデルの generateList メソッドを使用しましたが、このメソッドは CakePHP1.2 では非推奨メソッドになっているようです。その代わりに find メソッドを使用します。
$this->Model->generateList();
と書く代わりに
$this->Model->find('list');
と書きます。
find メソッドのこの書き方は他に
- find(‘count’)
- レコード数を取得する。COUNT(*) の SQL を実行する
- find(‘first’)
- 最初のレコードを取得する。 LIMIT 1 で SQL を実行する
- find(‘all’)
- 全てのレコードを取得する。findAll と同等。
findAll は内部で find(‘all’) を実行している。
などがあります。
CakePHP1.2 Form ヘルパーで日付のフォームを作る
1CakePHP1.2 の Form ヘルパーを使用して日付のフォームを作成したときのメモです。
$attr = array('minYear' => 2000, 'maxYear' => date('Y'), 'separator' => ' / '); echo $form->dateTime('Model/field', 'YMD', 'NONE', date('Y-m-d'), $attr);
とすると下のような日付を選択するフォームができます。
第2引数の ‘YMD’ で年月日の並び順を指定します。日付を表示しない場合は ‘NONE’ を指定します。
- NONE
- 非表示
- YMD
- 年月日の順に表示
- DMY
- 日月年の順に表示
- MDY
- 月日年の順に表示
第3引数で時間表示の指定をします。
- NONE
- 非表示
- 12
- 時間を12時間表示
- 24
- 時間を24時間表示
第4引数でデフォルトの日時を指定します。
第5引数で属性を指定します。
- separator
- 日付の select タグの間に表示する文字
- minYear
- 開始する年
- maxYear
- 終了する年
- interval
- 分を何分刻みで表示するか
CakePHP PHP4 のとき findByカラム名の注意点
1現在開発しているシステムで初めて PHP4 で CakePHP を使用しています。
PHP4 で CakePHP を使用するときの注意点です。
ユーザID で検索するときに findBy カラム名をよく使います。
$this->Model->findByUserId($user_id);
これを PHP4 で使用するときは
$this->Model->findByUser_Id($user_id);
とアンダーバーを入れる必要があります。
CakePHP Ajax のフォームを作成する
5今さらなのですが CakePHP1.1 で Ajax のフォームを作成するというのをやったのでメモしておきます。
Ajax , Javascript ヘルパーを使用できるようにする
コントローラで Ajax, Javascritp ヘルパーを使用できるようにする。
var $helpers = array('Ajax', 'Javascript');
prototype.js を読み込む
webroot/js に prototype.js を配置し、ビューで読み込みます。
<?php echo $javascript->link('prototype'); ?>
ビューでフォームを作成する
今回は submit ボタンを押した後、更新中には submit ボタンを消して変わりに「更新中」というメッセージを表示し、更新終了後にメッセージをボタンの下の id=ajax_message に表示するようにしました。
<?php $options = array( "update" => "ajax_message", "loading" => "Element.hide('ajax_button'); Element.show('ajax_loading');", "complete" => "Element.show('ajax_button'); Element.hide('ajax_loading');", ); echo $ajax->form("/controller/action/", "post", $options); ?> <?php echo $html->input('Model/Field', array('type'=>'text')); ?><br> <input type="submit" id="ajax_button"> <div id="ajax_loading" style="display:none;">更新中...</div> <div id="ajax_message"></div>
$ajax->form の $options の
“update” で更新するメッセージ領域を指定し、
“loading”でアップロード中の動き、
“complete” で処理終了後の動き
を指定しています。
コントローラに Ajax で処理するアクションを作成
function action() { $this->layout = 'ajax'; /* $this->data にフォームの内容が渡るので必要な処理を書く */ $this->Model->id = $this->data['Model']['id']; $this->Model->saveField("Field", $this->data['Model']['Field'], true); }
$this->layout で ‘ajax’ を指定して余計なヘッダ、フッタが出ないようにします。
Ajax で出力するビューを作成する
上のコントローラのアクションで出力するビューを作成します。
上の例では saveField でフォームから送られてきたデータを使用して更新処理しています。その結果によってメッセージを送信します。
<?php if($msg=$error->messageFor('Model/Field')) { echo $msg; } else { echo "更新しました"; } ?>
CakePHP1.2 バッチ処理
2CakePHP1.2 にシェル機能というのがあるのを知りました。下記エントリでメールからの処理を実際に行う方法が紹介されています。
メール受信からのシェル機能実行 – Writing Some Code
ちょうど CakePHP1.2で開発中のシステムで cron でのバッチ処理があるのでそれに応用してみたときのメモです。
バッチ処理で実行させるシェル機能を作成
今回は test という名前のシェル名にします。
app/vendors/shells/test.php を作成します。
< ?php class TestShell extends Shell { var $uses = array('Model'); function actionName(){ /* 実際の処理を書きます */ /* $this->uses に追加したモデルが使用できます */ $lists = $this->Model->findAll(); } } ?>
シェルスクリプト
下記のようなシェルスクリプトを作成して cron から実行させます。
#!/bin/sh cd /path/to/app ../cake/console/cake test actionName
シェルスクリプトなしで直接 cake を実行する方法もある
cake を実行するときにカレントディレクトリが app でないとだめなのですが、
-app /path/to/app
のように -app オプションで実行時に app のパスを指定することもできます。
その場合は下記のようになります。
/path/to/cake/console/cake test actionName -app /path/to/app
これを直接 cron から実行させればシェルスクリプトなしでも実行できます。
その他
vendors/shells 内のファイルですが、ファイル名が hoge_foo.php だった場合、クラス名は HogeFooShell ですが、実行するときは
cake/console/cake hoge_foo actionName
となるようです。
CakePHP PDT の補完機能をビューのヘルパーで使用する方法
1CakePHP のコーディングに PDT を使用しているのですが、ビューで補完機能を使用できるようにする方法が紹介されていました。
Eclipse PDTでCakePHP開発、まず設定すべきこと – Writing Some Code
ビューの拡張子(.ctp, .thtml) を PHP のコンテンツとして登録して、さらにビューで使用するヘルパーの各クラスのインスタンスを作るファイルをプロジェクトに作成し(場所はどこでもいいようです)PDT に教えてあげるような感じですね。
また、コントローラで使用するモデルやコンポーネントにも補完機能を使用できるようにする方法も紹介されています。
class AppController extends Controller { /** * @var Model */ var Model; /** * @var SessionComponent */ var $Session;
下記サイトも参考になりました。
Code completion in views with Eclipse PDT – cakebaker
Eclipse code completion in Views – Cake PHP | Google グループ
CakePHP1.2 モデルのビヘイビアを動的に切り替える
0CakePHP 1.2 から追加されたビヘイビアが動的に追加、削除できるようになるようです。
Attaching and detaching model behaviors on-the-fly – cakebaker
以前、CakePHP メール送信許可フラグによってメールを一斉送信するメールビヘイビア を書いたときに初めてビヘイビアというのを使ったのですが、ビヘイビアというのはうまく使えばかなり便利かなと思いました。
モデルに
var $actsAs = array('BehaviorName');
と書くことにより使えるようになるのですが、現在開発中の CakePHP1.2 でビヘイビアがモデルに attach , detach できるようになるようです。
ダウンロードできる最新の CakePHP 1.2.0.6311-beta にはまだ入っていませんが、以下より model.php のソースを手に入れて
cake/libs/model/model.php
に入れることによって試すことができます。
model.php のソース
モデルにビヘイビアをアタッチ、デタッチするのは以下のようになります。
$this->Model->attach('BehaviorName'); $this->Model->dettach('BehaviorName');
CakePHP メール送信許可フラグによってメールを一斉送信するメールビヘイビア
2Acts As Emailable | The Bakery, Everything CakePHP : Articles
メール送信許可フラグによってメールを一斉送信することができるメールビヘイビアが上記エントリで紹介されています。
ビヘイビアというのは今まで使ったことがなかったのですが、モデルに共通の振る舞いをさせるようなときに使う感じでしょうか。このメールビヘイビアはモデルにメールの一斉送信機能を付加します。
テーブル
CREATE TABLE `users` ( `id` int(11) NOT NULL auto_increment, `username` varchar(255) NOT NULL default '', `emailable` tinyint(4) NOT NULL default '1', `email` text NOT NULL, PRIMARY KEY (`id`) )
emailable カラムは 0 or 1 の値で、1の場合はメール送信許可です。
email カラムはメールアドレスが入ります。
モデル
app/models/user.php
< ?php class User extends AppModel { var $actsAs = array('emailable'); } ?>
モデルでメールビヘイビアを使うことを定義します。
ビヘイビア
Acts As Emailable | The Bakery, Everything CakePHP : Articles にメールビヘイビアのコードがあります。
これを app/models/behaviors/emailable.php として保存します。
ただし1点修正が必要でした。
322行目の
App::import('Component', 'EmailComponent');
を
App::import('Component', 'Email');
として保存してください。
Email コンポーネントが修正前のコードでは読み込めずにエラーになります。
メールテンプレート
< ?php echo "テストメッセージです。名前は".$username."です"; ?>
保存先ですが、どこがいいのか悩みましたが今回は app/views/emails/test_template.php としました。
テンプレート内の変数はモデルのカラム名が使用できます。
メール送信
$email_options = array('from' => 'hoge@example.com', 'subject' => 'テストです'); $template = "views/emails/test_template.php"; $this->User->send_campaign_to_emailable($template, $email_options);
これでメール送信許可している(users.emailable=1)のユーザにメールが送信されます。
そのほかに以下のようなメソッドがあります。
send_campaign_to_all($template, $email_options)
登録されているユーザ全てにメールを送信します。
send_campaign_to_non_emailable($template, $email_options)
登録されているユーザでメール送信許可していないユーザにメールを送信します。
add_emailable($id)
ID で指定したユーザの emailable=1 にします。
remove_emailable($id)
ID で指定したユーザの emailable=0 にします。
デフォルトは mail 関数でメール送信しますが、SMTP を指定して送信することもできます。
まとめ
このメールビヘイビアを今回試すことによってビヘイビアの使い方、便利さが少し理解できました。まだビヘイビアを試されていない方は一度試して見てはいかがでしょうか?
CakePHP コントローラに処理を書かずにモデルにメソッドを追加しよう!
2CakePHP だけではなくフレームワーク全般に当てはまることだと思います。
Fat models and how they change how you use the Model class – cakebaker
私もフレームワークを使い始めた当初はそうだったのですが、モデルに最初からあるメソッドだけを使用してコントローラでなんでもかんでもやってしまっていました。
そうではなく、もっとモデルにオリジナルのメソッドを追加して、コントローラではそれを使用した方がコントローラもすっきりして後から見たときにも何をしているか分かりやすいと思います。
例えばブログの最新エントリ10を find する場合コントローラに
$this->Post->findAll(array('Post.is_published' => true), null, array('Post.published DESC'), 10);
と書くよりも
Postモデル
function findMostRecent($limit = 10) { return $this->findAll(array('Post.is_published' => true), null, array('Post.published DESC'), $limit); }
コントローラ
$this->Post->findMostRecent();
と書いた方がコメントなどなくても何をしているのかが分かりやすくなります。
CakePHP 1.2 の saveAll その2
3CakePHP 1.2 の saveAll その1 では同一モデルへの複数レコードを saveAll で保存しました。今回はアソシエーションのモデルのデータを saveAll で保存する方法です。
アソシエーションのモデルのデータを保存
モデル
user.php
< ?php class User extends AppModel { var $name = 'User'; var $hasMany = array('Comment'); } ?>
comment.php
< ?php class Comment extends AppModel { var $name = 'Comment'; var $belongsTo = array('User'); } ?>
コントローラ
users_controller.php
function add() { if (!empty($this->data)) { $this->cleanUpFields(); $this->User->create(); if ($this->User->saveAll($this->data)===false) { $this->Session->setFlash('保存に失敗しました); } else { $this->Session->setFlash('保存しました'); } $this->redirect(array('action'=>'index'), null, true); } }
ビュー
users/add.ctp
< ?php echo $form->create('User');?> < ?php echo $form->input('User.name');?> < ?php echo $form->input('Comment.body'); ?> < ?php echo $form->end('Submit');?>
CakePHP 1.2 の saveAll その1 の同一モデルへの複数レコードの保存よりも使い道は多いのではないかと思います。
追記
このエントリーは CakePHP 1.2.0.6311 beta で検証しています。