Posts tagged model

CakePHP1.2 モデルの generateList は非推奨メソッドなので find(’list’) を使用する

3

CakePHP で 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 ヘルパーで日付のフォームを作る

1

CakePHP1.2 の Form ヘルパーを使用して日付のフォームを作成したときのメモです。

$attr = array('minYear' => 2000, 'maxYear' => date('Y'), 'separator' => ' / ');
echo $form->dateTime('Model/field', 'YMD', 'NONE', date('Y-m-d'), $attr);

とすると下のような日付を選択するフォームができます。

Form Helper Date

第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 バッチ処理

2

CakePHP1.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 の補完機能をビューのヘルパーで使用する方法

1

CakePHP のコーディングに 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 モデルのビヘイビアを動的に切り替える

0

CakePHP 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 メール送信許可フラグによってメールを一斉送信するメールビヘイビア

2

Acts 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 コントローラに処理を書かずにモデルにメソッドを追加しよう!

2

CakePHP だけではなくフレームワーク全般に当てはまることだと思います。
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

3

CakePHP 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 で検証しています。

Go to Top