質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

CakePHP3のバリデーションの使い方

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 2,264

cookie.

score 12

質問概要(追記あり)

CakePHPのバリデーションについて
フォームヘルパーから送られたパスワードの入力値(inputpass)とパスワード確認の入力値(inputpass2)をバリデーションのsameAsルールを使って一致しているかをチェックしたいのですが、
Error: TestsHelper could not be found.
というエラーがtest1ページで出力されて使えません。

==>上記は追記1で消えました。が、新たに
Error: Table "App\Model\Table\TestsTable" is not associated with "validationErrors"
というエラーが出ています。

下記に挙げるコードのどこが間違っているか、あるいは、
バリデーションの書き方をご存知の方がいればご指摘頂きたく願います。
よろしくお願いします。

前提(追記あり)

  • SQLデータベースについて
    CakePHPのSQL接続は完了し
    Testsテーブルに
    プライマリーキー、A_I_、のINTカラム「id」、
    VARCHARカラム「inputpass」
    がそれぞれ設定してあるとします。

  • ページ遷移について
    indexページから、test1ページにフォームの値をPOSTで送って
    test1ページで値のチェックをするとします。
    そして、saveメソッド、レコード追加はtest2ページでするものとして、
    test1ページでは、値のチェック、エラー表示のみを行うものとします。

  • モデルのテーブルファイル testsTable.php

<?php
namespace App\Model\Table;
use Cake\ORM\Table;

class TestsTable extends Table{
  public function sameAs($a,$b) {
    $v1 = array_shift($a);
    $v2 = array_shift($b);
    return $v1 == $v2;
}
  public $validator = [
        'inputpass' => [
          'alphaNumeric' => [
            'rule' => 'alphaNumeric',
            'message' => '半角英数字のみで入力してください'
          ],
          'minLength' => [
            'rule' => ['minLength',6],
            'message' => '6文字以上で入力してください'
          ]
        ],
        'inputpass2' => [
          'alphaNumeric' => [
            'rule' => 'alphaNumeric',
            'message' => '半角英数字のみで入力してください'
          ],
          'minLength' => [
            'rule' => ['minLength',6],
            'message' => '6文字以上で入力してください'
          ]
          'sameAs' => [
            'rule' => ['sameAs','inputpass','inputpass2'],
            'message' => 'パスワードが一致しません'
          ]
        ]
];
}
  • コントローラ TestsController.php
<?php
namespace App\Controller;

class TestsController extends AppController {
  public function initialize(){
    $this->name = 'Tests';
    $this->viewBuilder()->autoLayout(true);
    $this->viewBuilder()->layout('tests');
  }
  public function index(){
    $this->set('entity',$this->Tests->newEntity());
  }
  public function test1(){
    if($this->request->isPost()){
    $this->Tests->set($this->request->data);
  }
  public function test2(){
      if ($this->request->is('post')){
    $hoge = $this->Tests->newEntity($this->request->data);
    $this->Tests->save($hoge);
  }

}
}

コントローラTestsController.php追記1

<?php
namespace App\Controller;

class TestsController extends AppController {
  public function initialize(){
    $this->name = 'Tests';
    $this->viewBuilder()->autoLayout(true);
    $this->viewBuilder()->layout('tests');
  }
  public function index(){
    $this->set('entity',$this->Tests->newEntity());
  }
  public function test1(){
    if($this->request->isPost()){
    $this->Tests->set($this->request->data);
    $this->Tests->set($hoge);
    }else{
      $error = $this->Tests->validationErrors;
      $this->set('error',$error);
    }
  }
  public function test2(){
      if ($this->request->is('post')){
    $hoge = $this->Tests->newEntity($this->request->data);
    $this->Tests->save($hoge);
  }

}
}
  • テンプレートファイル test1.ctp
<?php
$error = array();
if($this->request->isPost()){
$this->Tests->set($this->request->data);
$inputpass = $this->request->data('inputpass');
$inputpass2 = $this->request->data('inputpass2');
if($this->Tests->validates()){
header("http://hoge/test2",true,303);
exit();
}else{
$error = $this->Tests->validationErrors;
}
}
if($this->request->isPost() && !is_null($error)){ ?>
<?=$this->Form->error('inputpass') ?>
<?=$this->Form->error('inputpass2') ?>
<?php } ?>
<br>
<a href="http://hoge/index.ctp">戻る</a> 

テンプレートtest1.ctp追記1

<?php
if($this->request->isPost()){
$this->Tests->set($this->request->data);
$inputpass = $this->request->data('inputpass');
$inputpass2 = $this->request->data('inputpass2');
if(is_null($error){
header("http://hoge/test2",true,303);
exit();
}
}
if($this->request->isPost() && !is_null($error)){ ?>
<?=$this->Form->error('inputpass') ?>
<?=$this->Form->error('inputpass2') ?>
<?php } ?>
<br>
<a href="http://hoge/index.ctp">戻る</a> 

自分で調べたこと

持っているCakePHPの参考書を読み倒してみると、バリデーションメソッドsameAsというのが、存在する様に書いてあるのですが、
あまり詳しい記述がなく
そのままだと使えなかったので、
今は自分でsameAsを定義して使おうとしています。
CakePHPの記事を検索エンジンでもかなり調べたのですが、
CakePHP自体の日本語記事が少ないこともあって、
解決できるものはありませんでした。
Error: UsersHelper could not be found.と出力されますが、
ヘルパーを用意しても解決しないので、
そもそもヘルパーを用意しなくても解決できる書き方が他にあって、
自分の書き方が間違っているのではないかと考えています。

==>上記は追記1により解決しました。
新たに出ている
Error: Table "App\Model\Table\TestsTable" is not associated with "validationErrors"
というエラー出力ですが、テーブルファイルの記述が間違っているのではないかと自分では考えています。

バリデーションを入力値チェックのみのページで使う書き方をご存知の方がいればご指摘してもらえると大変助かります。
よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

シンタックスエラーなのでPHPの文法がおかしいんだと思いますよ。たぶん、以下のカンマではないかと。

          'minLength' => [
            'rule' => ['minLength',6],
            'message' => '6文字以上で入力してください'
          ], // ここにカンマが足りない?
          'sameAs' => [
            'rule' => ['sameAs','inputpass','inputpass2'],
            'message' => 'パスワードが一致しません'
          ]

(追記)
シンプルなバリデーションの例を書いたので参考にしてください。

正直元のコードは内容がCakephp2の書き方だったり、そもそも文法も変だったりするので、基本的なところが理解できていいないと感じました。もっと基礎的な部分からじっくり勉強して理解していったほうがいいと思いますよ。

以下のコードの内容を軽く解説しておくと、バリデーションの定義は3系では配列ではなくオブジェクトに追加します。コントローラ側でnewEntity()にデータを渡すと自動的にバリデートが動いて、エラーがあればentityのerrors()で取得できます。
エラーをテンプレート側で表示したい場合、Formヘルパーのcreateにentityを渡してあげれば、対応するinputに自動的にエラーメッセージが表示されます。Cakephpでは、規約に従えば自動的に処理が実行されるものが多くあるので、よく理解することが大切だと思います。

TestsTable.php

<?php
namespace App\Model\Table;

use Cake\ORM\Table;
use Cake\Validation\Validator;

class TestsTable extends Table{

    public function validationDefault(Validator $validator) {
        $validator
            ->add('inputpass', [
                'length' => [
                    'rule' => ['minLength', 6],
                    'message' => '6文字以上で入力してください'
                ]
            ])
            ->add('inputpass2', [
                'length' => [
                    'rule' => ['minLength', 6],
                    'message' => '6文字以上で入力してください'
                ]
           ])
           ->add('inputpass2', [
                'sameAs' => [
                    'rule' => [$this, 'sameAs'],
                    'message' => 'パスワードが一致しません'
                ]
           ]);
        return $validator;
    }

    public function sameAs($value, $context) {
        if($value == $context['data']['inputpass']) {
            return true;
        }
        return false;
    }
}

TestsController.php

<?php
namespace App\Controller;

class TestsController extends AppController {

    public function test1() {
        if($this->request->isPost()) {
            $entity = $this->Tests->newEntity($this->request->data);
            if($entity->errors()) {
                debug('error');
            } else {
                debug('success');
            }
        } else {
            $entity = $this->Tests->newEntity();
        }
        $this->set(compact('entity'));
    }
}

test1.ctp

<?= $this->Form->create($entity) ?>
<?= $this->Form->input('inputpass') ?>
<?= $this->Form->input('inputpass2') ?>
<?= $this->Form->submit() ?>
<?= $this->Form->end() ?>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/03 13:33

    テンプレートからTestsテーブルにアクセスしようとしているのがおかしいので、Controller側に書くべきだと思います。

    キャンセル

  • 2017/02/03 14:44 編集

    ご指摘ありがとうございます。

    コントローラ側に書いて
    今度は
    Table "App\Model\Table\TestsTable" is not associated with "validationErrors"
    と出ました

    テーブルファイルの記述、おかしいですか?

    キャンセル

  • 2017/02/03 15:49

    回答に追記しました。あとはご自身で自分のコードや参考資料やマニュアルを良く読み理解してください。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる