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

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

新規登録して質問してみよう
ただいま回答率
85.48%
CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

Q&A

解決済

1回答

5067閲覧

cakePHP3で複数フィールドの挿入時におけるバリテーション&flashメッセージの表示

yajin

総合スコア75

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

0グッド

2クリップ

投稿2016/08/01 23:44

現在、複数フィールドの挿入のプログラムを書いているのですが、挿入はできるようになったものの、バリテーションによるエラーメッセージがうまく表示されません。
Entityの使い方についてよくわかってないと思うのですが、どのようにすべきなのでしょうか。

  • リストやりたいこと

一つでもエラーがあれば、処理を中止させて、エラーのflashメッセージとバリテーションの個々のメッセージを出して、もし一つもエラーがなければ、投稿完了のflashメッセージを出したいです。

php

1コントローラ 2 public function addition5(){ 3 $this->ViewBuilder()->layout('auth'); 4 $articles = TableRegistry::get('articles');//必要 5 $entities = $articles->newEntities($this->request->data()); 6 if($this->request->is('post')){ 7 $articles->connection()->transactional(function () use ($articles, $entities) { 8 foreach ($entities as $entity) { 9 $articles->save($entity, ['atomic' => false]); 10 } 11 }); 12 //var_dump($entities);これをするとエラーメッセージが格納されていることがわかる。 13 } 14 $this->set(compact('articles')); 15 $this->set('_serialize', ['articles']); 16 17 } 18

php

1ビュー 2echo $this->Form->create($articles,["class" => "article_form1"]); 3for($i = 0; $i < 5;$i++){ 4 $j = $i + 1;//エラーの配列番号と合わせるために足し算する。 5 echo '<h2 class="add5">登録記事('.$j.'/5)</h2>'; 6 echo $this->Form->hidden($i.'.user_id',['value' => h($this->request->session()->read('Auth.User.id'))]); 7 echo $this->Form->input($i.'.title',['label' => 'タイトル','placeholder' => 'タイトル']); 8 echo $this->Form->input($i.'.comment',['label' => 'コメント','placeholder' => 'コメント']); 9} 10echo $this->Form->button('登録',["class" => "ok"]); 11echo $this->Form->end();

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ビューに下記のコードを追加するとどうでしょうか。

PHP

1// カラム名がuser_idの場合 2echo $this->Form->error('user_id');

問題は解決したようですが、以下のコードの間違いを修正します。修正しないと気持ち悪いので…。
yajinさんの解決策通りフォームヘルパーには$entitiesを渡す方向です。

追記(修正)

PHP

1public function addition5() 2{ 3 $this->ViewBuilder()->layout('auth'); 4 $articles = TableRegistry::get('Articles'); 5 6 if ($this->request->is('post')) { 7 // ここでバリデーションが行われる 8 $entities = $articles->newEntities($this->request->data()); 9 10 // バリデーションでエラーが出た場合にここで処理を中断する 11 foreach ($entities as $entity) { 12 if ($entity->errors()) { 13 $this->set(compact('articles')); 14 return; 15 } 16 } 17 18 // 保存処理 19 $articles->connection()->transactional(function () use ($articles, $entities){ 20 foreach ($entities as $entity) { 21 $articles->save($entity, ['atomic' => false]); 22 } 23 }); 24 } else { 25 // POSTではない場合 26 $entities = $articles->newEntity(); 27 } 28 29 $this->set(compact('entities')); 30}

投稿2016/08/02 00:49

編集2016/08/09 02:19
coba-coba

総合スコア1409

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yajin

2016/08/02 01:11

ご返信ありがとうございます! 早速試してみたところ、 echo $this->Form->error($i.'.title'); echo $this->Form->error('.title'); 両方だめですね・・・。
coba-coba

2016/08/02 01:13

echo $this->Form->error('title');ではどうですか?
yajin

2016/08/02 01:19

あ、申し訳ございません。それでもだめです。 上のは誤植でした。ドットを抜かしてもだめですね。
yajin

2016/08/02 03:10

オブジェクト名がarticleなのかarticlesなのかentitiesなのかentityなのかが頭の中でごちゃごちゃしています・・・。
coba-coba

2016/08/02 05:21 編集

確かにごちゃごちゃしてきますよね。でも考え方は間違えていないと思います。 私も同じような書き方で試してみましたが、複数保存されて、ちゃんとバリデーションもされました。 謎ですね……。 ちなみにビューに echo $this->Form->error('title'); は追記せずできました。 yajinさんの書き方だと細かいところでエラーが出たので、コントローラーのコードを書き直して上に追記しました。 これだとどうでしょうか。 (yajinさんと考え方は同じなのでいける気はしませんが…) だめだったら、バリデーションのエラーメッセージが見れる場合の debug($entities); の出力を見せていただけますか?
yajin

2016/08/02 06:20

大変申し訳ございません。ありがとうございます。 echo $this->Form->create($articles,["class" => "article_form1"]); for($i = 0; $i < 5;$i++){ $j = $i + 1;//エラーの配列番号と合わせるために足し算する。 echo '<h2 class="add5">登録記事('.$j.'/5)</h2>'; echo $this->Form->hidden($i.'.user_id',['value' => h($this->request->session()->read('Auth.User.id'))]); echo $this->Form->input($i.'.title',['label' => 'タイトル','placeholder' => 'タイトル']); echo $this->Form->error('title'); echo $this->Form->input($i.'.comment',['label' => 'コメント','placeholder' => 'コメント']); echo $this->Form->error('comment'); } echo $this->Form->button('登録',["class" => "ok"]); echo $this->Form->end(); こういうことでいいんでしょうか?
yajin

2016/08/02 07:12 編集

debug($articles); [ (int) 0 => object(App\Model\Entity\Article) { 'user_id' => (int) 4, 'comment' => '', '[new]' => true, '[accessible]' => [ 'user_id' => true, 'title' => true, 'comment' => true ], '[dirty]' => [ 'user_id' => true, 'comment' => true ], '[original]' => [], '[virtual]' => [], '[errors]' => [ 'title' => [ 'length' => '2文字以上で入力してください。', 'custom' => '日本語のみは使用できません。' ] ], '[invalid]' => [ 'title' => 'a' ], '[repository]' => 'Articles' }, (int) 1 => object(App\Model\Entity\Article) { 'user_id' => (int) 4, 'comment' => '', '[new]' => true, '[accessible]' => [ 'user_id' => true, 'title' => true, 'comment' => true ], '[dirty]' => [ 'user_id' => true, 'comment' => true ], '[original]' => [], '[virtual]' => [], '[errors]' => [ 'title' => [ 'exist' => 'その記事名はすでに登録されています' ] ], '[invalid]' => [ 'title' => 'bb' ], '[repository]' => 'Articles' }, (int) 2 => object(App\Model\Entity\Article) { 'user_id' => (int) 4, 'comment' => '', '[new]' => true, '[accessible]' => [ 'user_id' => true, 'title' => true, 'comment' => true ], '[dirty]' => [ 'user_id' => true, 'comment' => true ], '[original]' => [], '[virtual]' => [], '[errors]' => [ 'title' => [ 'exist' => 'その記事名はすでに登録されています' ] ], '[invalid]' => [ 'title' => 'cc' ], '[repository]' => 'Articles' }, (int) 3 => object(App\Model\Entity\Article) { 'user_id' => (int) 4, 'comment' => '', '[new]' => true, '[accessible]' => [ 'user_id' => true, 'title' => true, 'comment' => true ], '[dirty]' => [ 'user_id' => true, 'comment' => true ], '[original]' => [], '[virtual]' => [], '[errors]' => [ 'title' => [ 'exist' => 'その記事名はすでに登録されています' ] ], '[invalid]' => [ 'title' => 'dd' ], '[repository]' => 'Articles' }, (int) 4 => object(App\Model\Entity\Article) { 'user_id' => (int) 4, 'comment' => '', '[new]' => true, '[accessible]' => [ 'user_id' => true, 'title' => true, 'comment' => true ], '[dirty]' => [ 'user_id' => true, 'comment' => true ], '[original]' => [], '[virtual]' => [], '[errors]' => [ 'title' => [ 'exist' => 'その記事名はすでに登録されています' ] ], '[invalid]' => [ 'title' => 'ee' ], '[repository]' => 'Articles' } ]
coba-coba

2016/08/02 13:56

情報ありがとうございます。 ビューのecho $this->Form->error('……');は無くても大丈夫でした。 すみません、消してもらって構いません。 頂いた情報からは特に問題は無いように思えます。 ただ、更に2つ気になる点があります。 すでにチェック済みかもしれませんが、念のため教えていただけますか。 1.addition5()はPOSTするときだけに使うのでしょうか。 addition5()を呼び出すときURLが「/コントローラー/addition5」でアクセスすると思うのですが、POSTしない場合(最初にアクセスする時)はエラーになると思います。 (この部分 → $entities = $articles->newEntities($this->request->data());) 2.addition5()で処理が終わった後、$this->redirect([……]);で飛んでいませんか。 $articlesがフォームヘルパーに渡されなければエラーメッセージは出ません。
yajin

2016/08/02 14:26

$entities = $articles->newEntities($this->request->data()); そうです。これがすごく悩んでました。postされたものを何度も書き直してバリテーションがでて嬉しくと思っていたら、再び新規に開いたらエラーと・・・ バリテーションがでると、新規で開けなくなり、また挿入できるようになるとバリテーションエラーが表示されないという繰り返しです。 何度もコメントアウトしてソースがいっぱいになり、ごちゃごちゃになってました。 ちょっと見返してみます。
coba-coba

2016/08/02 15:01

Entityのあたりはまりますよね…。 行き詰まったら、bakeで骨組みを作ってそこから少しずつ修正していくのが吉ですね。
yajin

2016/08/02 15:13

public function addition5(){ $this->ViewBuilder()->layout('auth'); $articles = TableRegistry::get('articles');//必要 if($this->request->is('post')){ $entities = $articles->newEntities($this->request->data()); foreach($entities as $entity){ if($entity->errors()){ $this->set(compact('articles')); return; } } $articles->connection()->transactional(function () use ($articles, $entities) { foreach ($entities as $entity) { $articles->save($entity, ['atomic' => false]); } }); }else{ $articles = $articles->newEntity(); } // echo "<pre>"; // debug($entities); // echo "</pre>"; $this->set(compact('articles')); } 現在このような形です。
yajin

2016/08/02 15:14

インデントが読みにくくてすみません・・・
coba-coba

2016/08/02 18:21

1つのレコードのみを保存する場合はバリデーションされるのでしょうか。まずは1つのレコードで試してみた方がいいと思います。 もし動かなければテーブルやエンティティの設定を間違えているのかもしれません。 基本的にnewEntity()やnewEntities()でエンティティを作って、それをフォームヘルパーに渡すだけです。
yajin

2016/08/02 23:49

大変恐れ入ります。 >1つのレコードのみを保存する場合はバリデーションされるのでしょうか。まずは1つのレコードで試してみた方がいいと思います。 これは可能です。しっかりとエラーメッセージが出ます。大文字小文字で意識するところはどんなところでしょうか?それぐらいしか考えられないです。error.logやdebug.logも何もでなくなりました。
coba-coba

2016/08/03 09:40

可能でしたか。そうするとますます謎ですね。 大文字小文字だと、 TableRegistry::get('articles') を'Articles'にするくらいでしょうか。 CakePHPのマニュアルには大文字で載っていますし。 全部小文字でも問題ないはずですが。
yajin

2016/08/04 01:00

まとめておきます。 ・複数レコードの挿入のプログラム 1、正しい情報が入った時には複数挿入はできる。 2、debug($entities)にはオブジェクト型で、errorsにバリテーションエラーメッセージの値が格納されていることが確認できる。 3、別アクションでの一つのレコード挿入時にはバリテーションエラーも出るし、挿入もできる。 ・解決できたこと 1、Post送信されていない場合(初回のアクセス)におけるエラーはなくなった。
yajin

2016/08/04 01:13

考えられたこと ・CSSのせい? display:none的なことが考えられるが、postされたあと、近辺をGCで検証を行ってみるも、タグが生成されていない。 ・inputをtextに代えてみた。 $this->Form->textに一度代えてみて、$this->Form->error('title')にしてみたが、表示されず。
coba-coba

2016/08/04 01:29

まとめありがとうございます。 最初に思いつきで書いてしまったのが悪かったのですが、項目は複数あるので少なくとも $this->Form->error('title'); ではなく、 $this->Form->error('0.title'); $this->Form->error('1.title'); となるはずです。
yajin

2016/08/04 02:37

本当にありがとうございます。 試してみたところ、だめですね。 一度はでたことがある(けど、postされていない場合にはアクセスエラー状態になっていた)ので、やはりControllerのプログラムのせいだと思います。
yajin

2016/08/05 09:04

coba-cobaさんいらっしゃいますでしょうか?
coba-coba

2016/08/05 14:14

いますよー。ちょくちょく考えてはいますが、私の実力だと直接見て動かしてみないと分からない状態です…。
yajin

2016/08/05 15:23

個人的に相談したいのですが、私のプロフィールからサイトに飛んでいただき、連絡取り合うこてゃ可能でしょうか? すごく困っています。
coba-coba

2016/08/05 23:08

すみません、そういうのはやらないようにしています。 内心では連絡を取り合えたら楽だとは思いますが。 でも、私も今回のご質問の件は解決したいので、どこかにプログラムとデータベースのダンプしたものをzipなどで置いておいてもらえれば、私も試してみることはします。 どうでしょうか?
yajin

2016/08/05 23:50

そうですよね。大変申し訳ございませんでした。 コントローラとビューとモデル部分だけでいいのでしょうか?
coba-coba

2016/08/06 11:37

遅くなってすみません。それで大丈夫です。
yajin

2016/08/07 17:51

こちらこそ遅くなってすみません。 アップロードはやはり許可が下りずできませんでした。 ただ、進展したので、お話します。 view ctpのForm->create($entities,[~~])とし、 controllerは以下にしたところvalitationエラーメッセージが出てきました! ただ、foreachで回されているようで、同じ文が2度でてきました。 public function addition5(){ $this->ViewBuilder()->layout('auth'); $articles = TableRegistry::get('Articles'); if($this->request->is('post')){ //postされた場合 $entities = $articles->newEntities($this->request->data()); foreach ($entities as $entity) { if($entity->errors()){ $this->set(compact('entities')); // debug($entity->errors()); // $this->set('_serialize', ['articles']); return; } } $articles->connection()->transactional(function () use ($articles,$entities){ foreach($entities as $entity){ $articles->save($entity,['atomic' => false]); } }); }else{ //初回アクセス $articles = $this->Articles->newEntity(); } //var_dump($entities); $this->set(compact('entities')); } あと少しだとは思うのですが、どのようにしたらよいでしょうか?
coba-coba

2016/08/07 23:59

よかったです! しかしすみませんでした。$articlesと$entitiesがごっちゃになっていました…。 newEntities()で作ったエンティティを渡してなかったんですね。 何で今まで見逃していたのか分からないくらいのミスでした。 時間をかけさせて本当にすみません。 初回アクセスの部分も$entitiesにすべきですね。 //初回アクセス $entities = $this->Articles->newEntity(); バリデーションが2度出るというのは、ビューに$this->Form->error()を加えていませんか? $this->Form->input()のみで結構です。 もし加えていなければ他の原因も考えてみます。
yajin

2016/08/08 03:01

よし、完璧です。出来ました。 おっしゃるとおり、$this->Form->error()を加えていました。 フラッシュメッセージも出ました。 とりあえず動きました。あとは細かいところは自分で調整していきます。 長い間ありがとうございました!
coba-coba

2016/08/08 15:06

あまりお役に立てなくてすみませんでした。 解決してよかったです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問