Transitionコンポーネント - checkPrev() について

最初に書いたサンプルでは完了画面に出てきた Transition#checkPrev だけど、この説明をした方が Transition#automate はわかりやすくなるのでこっちを先に。

Transition#checkPrev は引数に指定したアクションからちゃんときているかをチェックします。どうやってチェックしてるかは Transition コンポーネントが管理しているセッションのデータ構造をみた方がわかりやすいと思います。データ構造は以下のような形になってます。

array(
  '(ControllerName)' => array(
    '(actionName1)' => array(
      '(fieldName1_1)' => '(value1_1)',
              :
    ),
    '(actionName2)' => array(
      '(fieldName2_1)' => '(value2_1)',
                :
    ),
               :
    '(actionNameN)' => array(
      '(fieldNameN_1)' => '(valueN_1)',
               :
    ),
  ),
);

最初に書いたFooコントローラーの例だと以下のような感じ

array(
  'Foo' => array(
    'step1' => array(
      '(fieldName1_1)' => '(value1_1)',
              :
    ),
    'step2' => array(
      '(fieldName2_1)' => '(value2_1)',
                :
    ),
    'step3' => array(
      '(fieldNameN_1)' => '(valueN_1)',
               :
    ),
  ),
);

コンポーネントを使用しているコントローラ名をキーとして、その下に各アクション名をキーとした入力値が入っています。

Transition#checkPrevは引数に指定したアクション名をキーとしたデータがあるかどうかをチェックしてます。そのデータがなければそのアクションにリダイレクトしてデータ入力させるというわかりやすい形になっているってことですね。

というわけでおおざっぱに書いた展開コード

class FooController extends AppController {
  public $uses = 'Foo';
         :
  public function step3() {
    // $this->Transition->checkPrev('step2') のおおざっぱな展開コード
    $data = $this->Session->read('session_key');
    if (!isset($data['Foo']['step2']) {
      $this->redirect('step2');
    } 
  }
}

複数のアクションを通ったことをチェックしたい場合は引数に配列を指定できます。

class FooController extends AppController {
  public $uses = 'Foo';
         :
  public function add() {
    // $this->Transition->checkPrev(array('step1', 'step2', 'step3', 'confirm') のおおざっぱな展開コード
    $data = $this->Session->read('session_key');
    foreach (array('step1', 'step2', 'step3', 'confirm') as $step) {
      if (!isset($data['Foo'][$step]) {
        $this->redirect($step);
      }  
    }
  }
}

これまたおきまりのコードを1行でさらっと書けるのがいい感じ。ちなみに現在のセッションデータをデータ構造そのままで取得したい場合は Transition#allData、アクションのキーを全部取っ払ってデータを全部マージした状態のデータをとりたい場合は Transition#mergedData を使います。

Transition#mergedDataでデータを取得するとさっきのデータ構造が以下のような形になります。

array(
  'Foo' => array(
    '(fieldName1_1)' => '(value1_1)',
          :
    '(fieldName2_1)' => '(value2_1)',
          :
    '(fieldNameN_1)' => '(valueN_1)',
          :
    '(fieldNameN_M)' => '(valueN_M)',
  ),
)

そして、 Transition#clearData() はセッションデータをクリアしてくれます。正常に完了したらデータをクリアするという使い方になると思います。