CakePHP3を触ってみました 〜届け愛のエラーメッセージ〜

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
今にして思えば良い歌多かったなぁ

この記事を三行にまとめると

ロウで固めた鳥の羽を両手に持って飛び立ったのも、今は遠い昔の記憶
Formヘルパーには、エラーメッセージを表示する機能がちゃんとある
この記事書きながら、久しぶりにいろいろ聞き込んじゃったよ
とどけ〜あい〜のめ〜っせ〜じ〜♪

中学の時の文化祭で、マイバラードっていう歌を歌ったんですけど、あの歌、結構好きでした。

俺の中で、「〇〇バラード」っていうタイトルの歌は、良い歌が多いという印象がありますね。怪獣のバラードとか、虹と雪のバラードとか。

っていうか、バラードに関係なく、音楽の授業でやった歌って、良い歌多かったよなぁ……夢の世界を、瑠璃色の地球、翼をください、グリーングリーン……何もかもみな懐かしい。ロウで固めた鳥の羽を両手に持って飛び立ったのも、今は遠い昔の記憶。



まあそんなことはともかく、以前、バリデーションの処理について書いたことがありました。

バリデーションのバリエーション

あの時、バリデーションに引っかかった時のエラーメッセージは、CakePHP2と3で、それぞれ以下の部分に格納されているってなことを言いました。

//CakePHP2
$this->validationErrors

//CakePHP3
$entity->errors()

だからビューでエラーメッセージを表示する場合は、この変数からメッセージを取り出して使おうってな感じの言い方をしました。実際僕もそうやって使ってたんですが、Formヘルパーには、エラーメッセージを表示する機能がちゃんとあるんですよね。使ったことなかったんで、すっかり忘れてたわ。

なので、今日はそれでエラーメッセージを表示してみましょう。2でも3でも使い方は一緒なのですが、ほんのちょっ〜ち、フォームの書き方が異なるので、注意が必要っす。



CakePHP2

とりあえずコードを書いてみます。usersというテーブルにnameというカラムがあると思ってください。そこに名前を入れたいのだけど、未入力だとエラーになるっていう感じ。

//UsersController.php
class UsersController extends AppController {
  public function index() {
    if($this->request->is('post')) {
      $this->User->create($this->request->data);
      if($this->User->validates()) {
        //エラーなし、登録処理
      }
    }
  }
}

//User.php
class User extends AppModel {
  $validate = array(
    'name' => array(
      'rule' => 'notEmpty',
      'message' => '未入力です',
    ),
  );
}

//index.ctp
<?php echo $this->Form->create('User') ?>
  <?php echo $this->Form->text('name') ?>
  <?php echo $this->Form->error('name') ?>
<?php echo $this->Form->end() ?>

だいたいこんな感じ?

ビューの中に「$this->Form->error(‘name’)」というのがありますが、こいつを書いとけば、エラーがある場合に、メッセージを表示してくれます。今回はエラーの条件がnotEmptyの一つだけですが、もちろん複数書いた場合も、条件に該当するエラーメッセージを出してくれます。

<input name="data[User][name]" class="form-error" type="text" value="" id="UserName" />
<div class="error-message">未入力です</div>

デフォルトの設定だと、divで囲われたメッセージが表示されます。なので、CSSでerror-messageクラスのstyleを書いとけば、赤文字で表示したりできます。

もしdivタグを出したくないときや、div以外のタグで表示したいってときは、第三引数でwrapというオプションを設定すれば良い。

//divタグを出さない場合
<?php echo $this->Form->error('name', null, array('wrap' => false)) ?>

//divタグをpタグに変える場合
<?php echo $this->Form->error('name', null, array('wrap' => 'p')) ?>

ついでに言うと、エラー時はテキストボックスの方にも「form-error」というクラスが自動で付与されるので、そっちにもCSSを書いとけば、ボックスを赤く囲ったりできる。



CakePHP3

CakePHP3でも、基本は一緒です。ただし、フォームヘルパーのcreate()の書き方に、ちょい気をつけるべし。

//UsersController.php
namespace App\Controller;
use Cake\ORM\TableRegistry;

class UsersController extends AppController {
  public function index() {
    $table = TableRegistry::get('Users');
    $entity = $table->newEntity($this->request->data);

    if($this->request->is('post')) {
      if(!$entity->errors()) {
        //エラーなし、登録処理
      }
    }

    $this->set(compact('entity'));
  }
}

//UsersTable.php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;

class UsersTable extends Table {
  public function validationDefault(Validator $validator) {
    $validator->notEmpty('name', '未入力です');
    return $validator;
  }
}

//index.ctp
<?= $this->Form->create($entity) ?>
  <?= $this->Form->text('name') ?>
  <?= $this->Form->error('name') ?>
<?= $this->Form->end() ?>

CakePHP3でerror()を使う場合は、create()の第一引数にエンティティを渡してあげないといけないようです。CakePHP2のようにモデル名などを入れてると、メッセージが出てこない。そのためには、データがPOSTされてない状態でも、エンティティを作成しておかないといけませんね。

2の場合と同様、エラーメッセージはdivタグで囲われますが、3にはwrapというオプションがありません。divタグを消したかったりpタグに変えたい場合、一番簡単なのは、Viewフォルダの中にあるAppView.phpで設定することかな。

//AppView.php
public function initialize() {
  $this->loadHelper('Form', [
    'templates' => [
       'error' => '{{content}}',
    ]
  ]);
}

これでdivタグが出なくなります。

FormHelper.phpの中を見てみると、「$_defaultConfig」という変数の中に、初期設定が書かれています。エラーメッセージの初期設定もある。この中で変えたい部分を、AppView.phpに書けばオッケーってことですね。

//pタグに変える
public function initialize() {
  $this->loadHelper('Form', [
    'templates' => [
       'error' => '<p class="error-message">{{content}}</p>',
    ]
  ]);
}

//クラス名を変更する
public function initialize() {
  $this->loadHelper('Form', [
    'templates' => [
       'error' => '<div class="error">{{content}}</div>',
    ]
  ]);
}

//テキストボックスに付与されるform-errorクラス名を変える
public function initialize() {
  $this->loadHelper('Form', [
    'errorClass' => 'error',
  ]);
}

他にもいろいろありますが、それについては各自確認ってことでよろしくよろしこ。



input()を使った場合

text()の代わりにinput()を使った場合、error()を使わなくても、input()メソッドがエラーメッセージの表示までやってくれます。ただ強制的にエラーメッセージが出てしまうので、逆に出したくない場合はオプションで指定する必要があります。

//エラーメッセージが出る
<?php echo $this->Form->input('name') ?>

//エラーメッセージが出ない
<?php echo $this->Form->input('name', array('error' => false)) ?>






こんなとこでしょうか。

それにしても、マイバラードとか怪獣のバラードとか、音楽の授業でやった曲って、ほとんどyoutubeに上がってるんだね。この記事書きながら、久しぶりにいろいろ聞き込んじゃったよ。

今はほんとに、何でもネットで見つかる時代だな。CakePHP3に関する情報も、これからどんどん増えて行くと思います。その数ある中の一つとして、ここに書いてある情報がお役に立てば幸いです。



その他のCakePHP3を触ってみましたの記事はこちら
まとめという名の箸休め
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください