ページの遷移を管理するTransitionコンポーネント

Transitionコンポーネント1.0をリリースしました。
http://d.hatena.ne.jp/hiromi2424/20100617/1276757385

ソースはこちら

http://github.com/hiromi2424/TransitionComponent
画面右上あたり「Download Sources」をクリックすると、アーカイブがダウンロードできます。

pull request お待ちしています:)

イントロダクション

複数ページの入力画面、皆さんどういう処理をしていますか?


同じアクション内で遷移する場合、データが存在しるかチェックしてどこの位置にいるか判断して・・・と、色々と面倒ですよね。
他のアクションに分割しても似たような処理が続くことになります。


そこでTransitionコンポーネントの出番です。
このコンポーネントを使うと、大抵のページ遷移は1行(one-liner)で済むようになります。
そうでないページも、遷移用の処理の記述が少なくなることで大幅にすっきりします。

※注意

このコンポーネントは、内部でセッションを使用して遷移時のデータを保持しています。
セッションが利用不可能な場合、ほとんどの機能が使えなくなることに気をつけてください。

例示

簡単なコントローラの実装を見てみましょう。
ここでは、Userモデル、Enqueteモデルを使います。
+、架空のCAPTCHA(画像認証)関数を用いています。実装したことがないので適当です。

<?php
class UsersController{
	var $components = array('Transition');
	// 基本情報入力画面
	function register(){
		$this->Transition->checkData('register_enquete');
	}
	// アンケート
	function register_enquete(){
		$this->Transition->automate(
			'register_confirm', // 次のアクション
			'Enquete', // ヴァリデーションを行うモデル名
			'register_confirm' // 前のアクション
		);
	}
	// 確認画面
	function register_confirm(){
		$this->Transition->automate(
			'register_save', //次
			null, // カレントモデルで
			'register_enquete', // 前
			'validateCaptcha' // 架空の画像認証「検証」関数
		 );
		$this->set('data',$this->Transition->allData());
		$this->set('captcha',createCaptcha()); // 架空の画像認証「作成」関数
	}
	// 保存
	function register_save(){
		$this->Transition->checkPrev(array(
			'register', // この
			'register_enquete', // ように
			'register_confirm' // 複数指定できます。
		));
		if($this->User->saveAll($this->Transition->mergedData()){
			$this->Transition->clearData();
			$this->Session->setFlash(__('Register complete !!',true));
			$this->redirect(aa('action','index'));
		}else{
			$this->Session->setFlash(__('Register failed ...',true));
			$this->redirect(aa('action','register'));
		}
	}
}
?>

さて、画面の各機能については大体理解できると思います。

  1. 基本情報入力画面でUserモデルに保存されるデータを入力する。
  2. アンケート画面でEnqueteモデルに保存されるデータを入力する。
  3. 確認画面では、入力されたデータの表示と、画像認証を行う。
  4. 保存するアクションではsaveAll()してしまう。


では、各アクションに沿って解説していきたいと思います。

register()

checkData()というメソッドを使っています。
これは、自身のフォーム入力にバリデーションチェックをし、通ったら次のアクション(第一引数)に自動リダイレクトします。

register_enquete()

automate()というメソッドを使っています。
これは、このコンポーネントの機能を一括で行ってくれる、中核メソッドとなります。
前のアクション(第三引数)のデータがセッションにあるかチェックし、なかったらそのアクションにリダイレクトします。
更に、checkData()と同様の処理を行います。これは第一引数で次のアクション、第二引数でモデル名を指定します。

register_confirm()

引き続きautomate()を使っています。
register_enquete()と違うのは、第三引数のモデル名にnullが指定され、第四引数が指定されていることです。


第四引数には独自のバリデーションメソッドが指定できます。
書式はcall_user_func()などに渡されるcallback形式です。
渡されたメソッドは、(&$model,$data)といった引数で呼び出されます。


第二引数をnull(デフォルト)にすると、コントローラのカレントのモデル(Controller::modelClass)が自動的に参照されます。
このモデルの指定は複数指定が可能で、指定されたモデル全てに対してバリデートが実行されます。
今回は独自のバリデーションメソッドを使うので、単一のカレントモデルをはりぼてに見立てて実行させています。


更に、allData()というメソッドを使っています。
これは、セッションに保持されたデータを全て引き出します。
フォーマットは以下のようにアクション名をキーに持ちます。

<?php
array(
    'register' => array(
          // ... register()で保持されたデータ
    ),
    // ...他のアクションのデータ
)
?>
register_save()

checkPrev()というメソッドを使っています。
これは、automate()の第三引数の機能にあたり、前のアクションのデータがセッションにあるかチェックし、なかったらそのアクションにリダイレクトします。
アクション名は、文字列と配列どちらでも指定できます。
配列が指定されると、指定された全てのアクションのセッションデータをチェックします。


更に、mergedData()というメソッドを使っています。
これは、セッションにあるデータ全てを再帰的にマージ(array_merge_recursive())して返します。
これは保存時にも、確認画面用にも大変便利です。


最後に、clearData()というメソッドを使っています。
これは、このコンポーネントで保持していたセッションデータを全て破棄します。
遷移画面が複数ある場合は、delData()というメソッドを使って個別のアクションのセッションデータを破棄する必要があります。

補足

さて、大体のイメージが沸いたかと思います。
お気づきのように、全てのアクション(保存時を除く)のビューでの、フォームの指定先は自分自身です。

<?php echo $form->create('User',array('action' => $this->action)) ?>

といった指定をしてください。(1.3以降を使っているなら、$this->actionといった指定は不要になります。)


このコンポーネントの機能遷移図を載せておきます。

字・絵が汚いのは仕様です。諦めてください。
Q.ならなんで手書きにしたし A.ちまちまPCで図書くのめんどくさい+専用のCASEツール持ってない・知らない

その他機能

  1. checkData()、automate()の第一引数はController::redirect()に直接渡されます。

Transitionコンポーネントは詳細な設定ができます。
以下にプロパティの詳細を示しておきます。
これはコアコンポーネントと同様に、

<?php
	var $components = array('Transition' => array(/* プロパティの設定 */));
?>

といった指定ができます。

<?php var $automation = false; ?>

アクション名を配列のキーに、その他プロパティの設定の配列を値にとる配列を指定すると、コントローラのBeforeFilter()後に、自動的にautomate() されます。
設置例はコードに記載してあります。または、後に作る詳細リファレンスを読んでください。

<?php var $messages = array(); ?>

前のアクションのデータが取得できなかった場合とバリデーション失敗時、setFlash()に渡されるメッセージを指定します。それぞれ'prev'、'invalid'がキーになります。それぞれの値にfalseを渡すとsetFlash()されません。

<?php var $autoComplete = true; ?>

このプロパティがtrueの場合、一度そのアクションのデータがセッションに保持されると、次に同じアクションにアクセスするとき、セッションデータから自動でController::dataにデータをリストアしてくれます。

<?php var $autoRedirect = true; ?>

このプロパティをfalseにすると、自動でリダイレクトを行いません。

<?php var $models = null; ?>

デフォルトのバリデーション用モデルが指定できます。

<?php var $validationMethod = null; ?>

デフォルトのバリデーションメソッドが指定できます。

詳細なAPIリファレンス

ソースを見てください、と言いたいところですが、後に日本語で参照できるようにまとめます。

最後に

まだまだ細かいところで不親切なところがあります。
何か困った点があったり、質問があったらバシバシ聞いてください。
今後の開発にほぼ即反映させてゆきます。:D


追記:
酷いtypoが多かったので(特にサンプルコード)、若干修正しました:D