CakePHP3でページ遷移をPOSTで管理するプラグインの紹介

#CakePHP3でページ遷移をPOSTで管理するプラグインの紹介

はい、本日でついに10の位が一つ上がってしまったsatthiです。おはこんにちばんわ。

~~そろそろ何かビームとか出せそう~~

##というわけで
せっかく、Cake3のAdventCalendarの招待をいただいたので何か書こうと思った！・・・

んですが、最近**Cake3全然触ってねぇw**ってことに気づいたので、前作ったプラグインでも紹介~~してお茶を濁しておこう！~~

##CakePHP2のページ遷移
といえば何といっても[TransitionComponent](https://github.com/hiromi2424/TransitionComponent)ですよね！

特徴としては
- 簡単にかける
- GETでページ遷移をしていくので画面単位で処理が書ける
- 画面ごとにURLが変わる
- **複数タブでの動作には対応していない**

といったところになります。

実は案件の性質上、太字で書いていることが問題になることがボチボチあったりします・・・。

##CakePHP3でページ遷移を作るにあたって
いざ複数ページ遷移のシステムを作ろうとしたときに、当然プラグインなんてまだ整備が進んでませんので、自分で作らないといけないわけですよ。

その際に

- 簡単にかける
- 処理は出来れば画面単位にまとめたい
- **ページ遷移はPOSTにする**

ということを考えることにしました。

幸いCake3はPHP5.4以上なのでTraitが使えちゃう！ってことで絶賛Traitを使って実装しました。

##PostTransitionプラグインの使用方法

[PostTransition](https://github.com/satthi/PostTransition)

使い方の詳細は[README](https://github.com/satthi/PostTransition/blob/master/README.md)を見てもらうとして、使い方の概要としては

①composerでインストール

```
{
    "require": {
        "satthi/post-transition": "*"
    },
}

```

②使用したいControllerにtraitを記述

```php
<?php
namespace App\Controller;
use App\Controller\AppController;
//これと
use PostTransition\Controller\PostTransitionControllerTrait;

class TopicsController extends AppController
{
    //これ
    use PostTransitionControllerTrait;
```

③使用したいメソッドに設定値を記載

```php
    public function add()
    {
        $settings = [
            //次へボタンのprefix(default はnext)
            //'nextPrefix' => 'next',
            //前へボタンのprefix(default はback)
            //'backPrefix' => 'back',
            //現在の状態をセッションで管理するキー(defaultはnow)
            //'nowField' => 'now',
            //扱うモデル
            'model' => 'Topics',
            //初期遷移時の設定
            'default' => [
                //初期値
                //'value' => [],
                //初期画面の設定はpost配列内のどの設定か
                'post_setting' => 'index1',
            ],
            //post時の設定
            'post' => [
                //key値は、ボタン名や独自メソッドへのアクセスに使用
                'index1' => [
                    //使用するview
                    'render' => 'index1',
                    //バリデーションをかける際のentity作成第二引数の設定
                    'validate_option' => ['validate' => 'index1']
                ],
                'index2' => [
                    'render' => 'index2',
                    'validate_option' => ['validate' => 'index2']
                ],
                'index3' => [
                    'render' => 'index3',
                    'validate_option' => ['validate' => 'index3']
                ],
                'save' => [
                    'render' => false,
                    'validate_option' => ['validate' => false]
                ],
            ],
        ];
        $this->__postTransition($settings);
    }
```

③画面特有の処理を行いたいときは専用のprivateメソッドで記載(デフォルトで__画面名だが、メソッド名は独自に指定も可能)

```php
    //index1の画面描画前(entityセット直前でフック)
    private function __index1($entity){
       $entity->hoge4 = 'are';
    }

    //save処理
    private function __save($entity){
        debug($entity);
        //save 処理
        exit;
    }
```

④各viewを作成

index1.ctp

```php
index1<br />
<?php //__index1にてentityにセットした値が入る?>
hoge4:<?= $entity->hoge4;?><br />
<?= $this->Form->create($entity);?>

<?= $this->Form->input('hoge1',['required' => false]);?>
<?= $this->Form->input('hidden_key');?>

<?php //押すと、index1のバリデーションがかかった後index2.ctpが表示?>
<?= $this->Form->submit('submit', ['name' => 'next_index2']);?>
<?= $this->Form->end();?>
```

index2.ctp

```php
index2<br />
hoge1:<?= $entity->hoge1;?>

<?= $this->Form->create($entity);?>

<?= $this->Form->input('hoge2',['required' => false]);?>
<?= $this->Form->input('hidden_key');?>

<?php //バリデーションをかけず画面1に戻る?>
<?= $this->Form->submit('back', ['name' => 'back_index1']);?>
<?php //index2のバリデーションをかけて画面3にすすむ?>
<?= $this->Form->submit('next', ['name' => 'next_index3']);?>
<?= $this->Form->end();?>
```

index3.ctp

```php
index3<br />
hoge1:<?= $entity->hoge1;?><br />
hoge2:<?= $entity->hoge2;?><br />
<?= $this->Form->create($entity);?>

<?= $this->Form->input('hoge3',['required' => false]);?>
<?= $this->Form->input('hidden_key');?>

<?php //バリデーションをかけず画面1に戻る?>
<?= $this->Form->submit('back1', ['name' => 'back_index1']);?>
<?php //バリデーションをかけず画面2に戻る?>
<?= $this->Form->submit('back2', ['name' => 'back_index2']);?>
<?php //バリデーションをかけてsave処理にすすむ?>
<?= $this->Form->submit('next', ['name' => 'next_save']);?>
<?= $this->Form->end();?>

```

view作成時のポイントは、submitボタンのname属性のつけ方です。

back_(画面名)で**バリデーションをかけずに該当画面に遷移します**

```php
<?= $this->Form->submit('back', ['name' => 'back_index1']);?>
```

next_(画面名)で**バリデーションをかけてに該当画面に遷移します**

```php
<?= $this->Form->submit('next', ['name' => 'next_index3']);?>
```

##まとめ
それなりにはきれいにまとめたつもりです。

まぁ自分が使って使いやすいように使ったので他の人にとって都合がよいかは分かりませんが、CakePHP2でPOSTで画面遷移を作らないといけない時に画面単位で処理がまとめられなかった件については解決できたのかなーとか思ってます。