CakePHP バリデーションメッセージの表示

PHP 5.5.31
CakePHP 2.8.0

CakePHPでバリデーションメッセージを表示する方法をまとめます。この方法はCakePHPにおいてスタンダードなバリデーション表示方法です。
今回は例として、アカウント作成に失敗したらバリデーションメッセージを出力します。
ユーザ作成の入力項目は、名前、メールアドレス、パスワードとします。
ユーザ編集の入力項目は、名前、メールアドレスとします。
バリデーションの内容は、名前入力必須、メールアドレス必須、有効なメールアドレスか確認、メールアドレスの重複確認、パスワードの文字数6文字以上とします。

# 例で使用するコントローラー名など
## 新規作成画面、詳細画面
  |  名前
--- | :-:
コントローラー | HogesController.php
追加画面のアクション | create()
追加処理のアクション | add() <br> 成功時：create()にリダイレクト <br> 失敗時：add()でエラー表示
詳細画面のアクション | show()
編集処理のアクション | update() <br> 成功時：show()にリダイレクト <br> 失敗時：update()でエラー表示
アカウント新規作成画面 | create.ctp
アカウント編集画面 | show.ctp
モデル | Hoge.php

## Hogeモデルのカラム

  |  カラム名
--- | :-:
名前 | name
メールアドレス | mail
パスワード | password

# バリデーション
`Hoge.php`にバリデーション内容を書く。
公式ドキュメントを参考に記述した。
http://book.cakephp.org/2.0/ja/models/data-validation.html

```Hoge.php
class Hoge extends AppModel {

	public $validate = [
		'name' => [
			[
				'rule' => 'notBlank',
				'message' => '名前は必須入力の項目です。',
			],
		],
		'mail' => [
			[
				'rule' => 'notBlank',
				'message' => 'メールアドレスは必須入力の項目です。',
			],
			[
				'rule' => ['email', true],
				'message' => '有効なメールアドレスを入力してください。',
			],
			[
				'rule' => 'isUnique',
				'message' => '入力されたメールアドレスは既に登録されています。',
			],
		],
		'password' => [
			[
				'rule' => ['minLength', 6],
				'message' => 'パスワードは6文字以上です。',
			],
		],
	];

}
```

# アカウント新規作成画面
## create()アクション
今回は引き渡すデータが特に無いので記述は特に無し。

```HogesController.php
public function create() {

}
```

## ビュー(create.ctp)
```create.ctp
<?=$this->Form->create('Hoge', ['url' => ['action' => 'add']])?>
	<?=$this->Form->input('name', ['placeholder' => 'ユーザ名を入力してください', 'label' => 'ユーザ名'])?>
	<?=$this->Form->input('password', ['placeholder' => 'パスワードを入力してください', 'label' => 'パスワード'])?>
	<?=$this->Form->input('mail', ['placeholder' => 'メールアドレスを入力してください', 'label' => 'メールアドレス'])?>
	<?=$this->Form->submit('登録', ['onclick' => 'return confirm("登録してよろしいですか？");'])?>
<?=$this->Form->end()?>
```

## 表示例
![スクリーンショット 2016-04-28 17.15.17.png](https://qiita-image-store.s3.amazonaws.com/0/42625/27b9b05f-56cd-02b0-31b1-21247aef0fc1.png)


# アカウント新規作成処理
## コントローラー(HogesController.php)

```HogesController.php
public function add() {

	$user = $this->request->data('Hoge');

	if ($this->Hoge->save($user) === false) {
		// 処理が失敗した時にcreateアクションを描画する
		return $this->render('create');
	}

	$this->setFlashInfo('ユーザーを新規登録しました');
	// 処理が成功した時にcreateアクションを描画する
	return $this->redirect(['action' => 'create']);

}
```

# バリデーションメッセージの表示例
メールアドレスの形式が間違ってる場合
![スクリーンショット 2016-04-28 17.19.45.png](https://qiita-image-store.s3.amazonaws.com/0/42625/96e53198-6302-0ece-c2b5-910400d83238.png)

パスワードの文字数が少ない場合
![スクリーンショット 2016-04-28 17.20.59.png](https://qiita-image-store.s3.amazonaws.com/0/42625/386f1739-5d50-575e-5c6d-314d587ca4d4.png)

# アカウント詳細画面(編集)
## 編集するユーザの例
カラム  | 値
--- | :-:
name | HogeFuga
mail | hoge@gmail.com

## show()アクション
IDで登録されたユーザの詳細画面を見られるものとする。
showは他でも利用するためprivateでメソッド化している。

```HogesController.php
/**
 * 管理ユーザー編集画面
 */
public function show($id) {
	$this->_show($id);
}

private function _show($id) {
	// 選択されたユーザ情報
	$user = $this->Hoge->findById($id)['Hoge'];
	// ユーザーが見つからなかった時のエラー処理
	if (empty($user)) {
		if (empty($this->referer())) {
			return $this->redirect('/');
		}
		return $this->redirect($this->refere());
	}

	$this->set([
		'name' => $user['name'],
		'mail' => $user['mail'],
	]);
	// 編集処理を行った後にshowアクションを描画する
	$this->render('show');
}
```

## ビュー(show.ctp)
```HogesController.php
<?=$this->Form->create('Hoge', ['url' => ['action' => 'update', $id]])?>

	<?=$this->Form->input('name', ['default' => $name, 'label' => 'ユーザ名'])?>
	<?=$this->Form->input('mail', ['default' => $mail, 'label' => 'メールアドレス'])?>
	<?=$this->Form->submit('更新', ['onclick' => 'return confirm("変更してよろしいですか？");'])?>

<?=$this->Form->end()?>
```

## 表示例
![スクリーンショット 2016-04-29 11.47.14.png](https://qiita-image-store.s3.amazonaws.com/0/42625/141a3e88-302a-2b05-f5a3-4e649549c49a.png)

# アカウント編集処理
```HogesController.php
public function update($id) {

	$user = $this->request->data('Hoge');
	$user['id'] = $id;

	if ($this->Hoge->save($user) === false) {
		$this->setFlashWarning('ユーザーの編集に失敗しました');
		// 処理が失敗した時に_showアクションを描画する
		return $this->_show($id);
	}
	$this->setFlashInfo('ユーザーを編集しました');
	// 処理が成功した時にshowアクションを描画する
	return $this->redirect(['action' => 'show']);

}
```

# バリデーションメッセージの表示例
メールアドレスの形式が間違っている場合
![スクリーンショット 2016-05-02 21.48.49.png](https://qiita-image-store.s3.amazonaws.com/0/42625/f2affbae-cda5-299b-daa6-691b459d0cd6.png)


# メリット
CakePHPが勝手にフォームの入力情報をバリデーションチェック後も埋めてくれ、かつバリデーションメッセージの追加表示してくれる。
バリデーションの結果にかかわらず、画面遷移が1回だけなので通信回数も1回である。

# デメリット
バリデーションの結果によって描画するビューファイルを変えているので、場合によってはそのビューに合わせてコントローラーからビューに必要な値を渡す必要がある。本記事の場合、updateアクションが該当する。
本記事中では、その処理を_show()というメソッドに切り出すことで、同じ処理を何度も書かないようにしている。