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

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

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

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

Q&A

解決済

1回答

4735閲覧

CakePHP3でコントローラからバリデーションエラーを追加する方法

samuraiders

総合スコア63

CakePHP

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

1グッド

1クリップ

投稿2018/09/18 16:33

前提・実現したいこと

CakePHP3のModelで行うバリデーションとは別に、コントローラでバリデーションを行いたいと考えております。
親子関係のあるテーブルがあり、子は親に対して複数登録可能です。(テーブルは以下の通り)

parentsテーブル

idmaximum
1100
2200

childrenテーブル

idparent_idnum
1150
2150

parents.maximumは、親に対して子が持てるnumの合計最大値となっており、numの合計値がmaximumを超えた時にエラーを発生させたいと考えております。
一つのアクションで親子両方更新する場合のバリデーションを想定しております。

ViewからPOSTした際の構造は以下の通りとなっております。

php

1{ 2 "maximum": 100, 3 "children": [ 4 { 5 "num": 50, 6 }, 7 { 8 "num": 50, 9 }, 10 ] 11} 12

発生している問題・エラーメッセージ

下記コードで、parents.maximumに対してはバリデーションエラーを追加することができたのですが、

php

1$parents->errors('maximum', 'エラーメッセージ');

以下の様に記載しても、$parents->errors()自体に値は入るのですが、実際にViewではエラーが表示されておらず、子に対してエラーを追加する方法がわかりません。

php

1$parents->errors(['children' => [0 => ['num' => 'エラーメッセージ']]]);

上記コードを両方記載した時の$parents->errors()のをデバッグした結果は以下です。

php

1Array 2( 3 [maximum] => Array 4 ( 5 [0] => エラーメッセージ 6 ) 7 8 [children] => Array 9 ( 10 [0] => Array 11 ( 12 [num] => Array 13 ( 14 [0] => エラーメッセージ 15 ) 16 ) 17 ) 18)

View側の記載に誤りは無いと考えており、その理由はChildrenTableで定義した$validatorで発生したエラーはViewでも正常にエラーが表示されております。

お手数ではございますが、何卒よろしくお願いいたします。

ちなみにですが、モデル側で解決できる案でも構いません。

以上、よろしくお願いいたします。

popobot👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

手元の環境で、軽く実験した感じだと以下のようにやればできそうでした。

$parents->errors(['children.0.num' => [0 => 'エラーメッセージ']]);

追記

さらに手元の環境で検証した結果、以下のようにやればできました。

$parents->children[0]->errors(['num' => ['エラーメッセージ']]);

最初の回答は、自分の環境で特殊なことをやっていたため、表示されていました...大変失礼しました。

投稿2018/09/20 10:15

編集2018/09/27 13:33
popobot

総合スコア6586

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

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

samuraiders

2018/09/27 10:16 編集

ご回答ありがとうございます。 その方法も試していたのですが、$parents->errors()内のデータ構造が違う形になってしまいます。 例えば、バリデーションで発生したエラーは、 Array ( [children] => Array ( [0] => Array ( [num] => Array ( [error] => エラーメッセージ ) ) ) ) となりますが、ご教授頂いた方法ですと、 Array ( [children.0.num] => Array ( [0] => エラーメッセージ ) ) となってしまいます。 もちろん、View側ではエラーは発生していない状態です。
popobot

2018/09/27 10:35

なんででしょうね... View側のコードも見てみないとなんと言えないです
popobot

2018/09/27 10:37

後、バリデーションのエラーを再現させるなら、配列が一段足りないですね。 以下だとどうなるんでしょうか $parents->errors(['children' => [0 => ['num' => ['error' => 'エラーメッセージ']]]]);
samuraiders

2018/09/27 11:08

ご回答ありがとうございます。 それも過去に試したことがあり、再度試してみました。 バリデーションで発生したエラーと同じ構造なので、いけるかと思ってたのですが、期待通りの結果は得られませんでした。 その時のerrors()の内容を添付します。 Array ( [children] => Array ( [0] => Array ( [num] => Array ( [error] => エラーメッセージ ) ) ) ) そして、viewの書き方ですが、 <?= $this->Form->control('children.' . $i . '.num', [ 'type' => 'text', 'label' => [ 'text' => 'ナンバー' . $i, 'escape' => false, ], ]) ?> です。(forで回しているので$iが付与されています) バリデーションで発生したエラーは画面上にエラーとして表示される、且つその時の配列構造と同じなのになぜ画面上に表示されないのかが、非常に不可解です。。
popobot

2018/09/27 11:30

errorsを設定している$parentsというEntityがView側に渡っていないという可能性はないでしょうか View側のForm->create()にそのEntityを渡していますか 試しにView側のEntityの内容も出力してみるとなにかわかるかもしれません
popobot

2018/09/27 13:34

すみません、さらに検証した結果、最初の回答は間違っていました。 新しいやり方を回答欄に追記したので試していただけますでしょうか。
samuraiders

2018/09/27 15:43

何度もご回答頂きありがとうございます。 そして、追記して頂いた方法で意図した動作が行えました! $parents->children[0]->errors(['num' => ['エラーメッセージ']]); Controllerでエラーを確認する稀なケースではありますが、非常に助かりました。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問