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

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

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

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

Q&A

解決済

1回答

7805閲覧

cake PHP3 アソシエーションsave

sbc

総合スコア21

CakePHP

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

0グッド

0クリップ

投稿2017/02/07 00:57

編集2017/02/07 04:09

###前提・実現したいこと
cakePHP3にて、一つの登録フォームで複数テーブル(アソシエーション)に保存したい。

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

The member could not be saved. Please, try again. (Controllerの保存処理エラー)

###該当のソースコード
MemberController

public function register() { $member = $this->Member->newEntity(); if ($this->request->is('post')) { $member = $this->Member->newEntity($this->request->data, [ 'associated' => ['MemberDetail'] ]); if ($this->Member->save($member)) { $this->Flash->success(__('The member has been saved.')); return $this->redirect(['action' => 'login']); } $this->Flash->error(__('The member could not be saved. Please, try again.')); } $this->set(compact('member')); $this->set('_serialize', ['member']); }

MemberTable

class MemberTable extends Table { public function initialize(array $config) { parent::initialize($config); $this->addBehavior('Timestamp', [ 'events' => [ 'Model.beforeSave' => [ 'created_at' => 'new', 'updated_at' => 'existing', ] ] ]); $this->table('member'); $this->displayField('id'); $this->primaryKey('id'); $this->hasMany('AmusementPointHistory', [ 'foreignKey' => 'member_id' ]); $this->hasMany('MemberDetail', [ 'foreignKey' => 'member_id' ]); $this->hasMany('MemberDevice', [ 'foreignKey' => 'member_id' ]); $this->hasMany('TrophyAcquireHistory', [ 'foreignKey' => 'member_id' ]); $this->belongsToMany('Card', [ 'foreignKey' => 'member_id', 'targetForeignKey' => 'card_id', 'joinTable' => 'member_card' ]); } public function validationDefault(Validator $validator) { $validator ->allowEmpty('id', 'create'); $validator ->requirePresence('login_id', 'create') ->notEmpty('login_id') ->add('login_id', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']); $validator ->requirePresence('login_password', 'create') ->notEmpty('login_password'); $validator ->requirePresence('mail_address', 'create') ->notEmpty('mail_address') ->add('mail_address', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']); $validator ->allowEmpty('remainder_hash'); $validator ->dateTime('last_login_at') ->allowEmpty('last_login_at'); $validator ->integer('is_active') ->requirePresence('is_active', 'create') ->notEmpty('is_active'); $validator ->allowEmpty('admin_memo'); $validator ->integer('is_deleted') ->requirePresence('is_deleted', 'create') ->notEmpty('is_deleted'); $validator ->allowEmpty('created_by'); $validator ->dateTime('created_at') ->requirePresence('created_at', 'create') ->notEmpty('created_at'); $validator ->allowEmpty('updated_by'); $validator ->dateTime('updated_at') ->requirePresence('updated_at', 'create') ->notEmpty('updated_at'); return $validator; } public function buildRules(RulesChecker $rules) { $rules->add($rules->isUnique(['login_id'])); $rules->add($rules->isUnique(['mail_address'])); return $rules; } public function updateLastLoginAt($user) { $data = $this->get($user['id']); $data->last_login_at = Time::now(); $this->save($data); } }

MemberDetailTable

public function initialize(array $config) { parent::initialize($config); $this->addBehavior('Timestamp', [ 'events' => [ 'Model.beforeSave' => [ 'created_at' => 'new', 'updated_at' => 'existing', ] ] ]); $this->table('member_detail'); $this->displayField('id'); $this->primaryKey('id'); $this->belongsTo('Member', [ 'foreignKey' => 'member_id', 'joinType' => 'INNER' ]); } public function validationDefault(Validator $validator) { $validator ->allowEmpty('id', 'create'); $validator ->allowEmpty('nickname'); $validator ->integer('gender') ->allowEmpty('gender'); $validator ->date('birthday') ->allowEmpty('birthday'); $validator ->integer('country') ->allowEmpty('country'); $validator ->integer('prefecture') ->allowEmpty('prefecture'); $validator ->integer('language') ->allowEmpty('language'); $validator ->allowEmpty('created_by'); $validator ->dateTime('created_at') ->requirePresence('created_at', 'create') ->notEmpty('created_at'); $validator ->allowEmpty('updated_by'); $validator ->dateTime('updated_at') ->requirePresence('updated_at', 'create') ->notEmpty('updated_at'); return $validator; } public function buildRules(RulesChecker $rules) { $rules->add($rules->existsIn(['member_id'], 'Member')); return $rules; }

register.ctp

<div class="member form large-9 medium-8 columns content"> <?= $this->Form->create($member) ?> <fieldset> <legend><?= __('新規会員登録') ?></legend> <?php echo $this->Form->input('member_detail.0.nickname'); echo $this->Form->select('member_detail.0.gender', [0, 1, 2]); echo $this->Form->input('member_detail.0.birthday', ['type' => 'date']); echo $this->Form->select('member_detail.0.country', [1, 2, 3, 4, 5]); echo $this->Form->select('member_detail.0.prefecture', [1, 2, 3, 4, 5]); echo $this->Form->select('member_detail.0.language', [1, 2, 3, 4, 5]); echo $this->Form->input('mail_address', ['type' => 'email']); echo $this->Form->hidden('login_id', ['type' => 'text']); echo $this->Form->input('login_password', ['type' => 'password']); echo $this->Form->hidden('remainder_hash'); echo $this->Form->hidden('last_login_at', ['empty' => true]); echo $this->Form->hidden('is_active'); echo $this->Form->hidden('admin_memo'); echo $this->Form->hidden('is_deleted'); echo $this->Form->hidden('created_by'); echo $this->Form->hidden('created_at'); echo $this->Form->hidden('updated_by'); echo $this->Form->hidden('updated_at'); ?> </fieldset> <?= $this->Form->button(__('Submit')) ?> <?= $this->Form->end() ?> </div>

###試したこと
Viewのバリデーションで引っかかっているのかと思い、入力させたくないフィールドを削除したのですが、変わりませんでした。

###補足情報(言語/FW/ツール等のバージョンなど)
php7.1.1 / cake PHP3.3.12/

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

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

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

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

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

popobot

2017/02/07 02:41 編集

saveの直前でdebug($member->errors());を実行すると何か表示されますか? debug($member);を見てみるのもいいと思いますよ。
sbc

2017/02/07 02:42

やってみます!
guest

回答1

0

ベストアンサー

バリデートで色々エラーが出ているかだと思いますよ。

save()を実行する前にはバリデートでエラーが出ていないかerrors()を見るべきです。エラーがあるならsave()は実行せずにreturnして入力画面に戻したらいいと思います。
※newEntityで内部的にはバリデーションが自動的に実行されerrors()でバリデーションの結果が閲覧できます。

ただ、現状発生しているのはhiddenなものが多いですね... バリデーションが適切か見直してください。特にユーザが入力しない項目ならinput自体やめて、バリデートもやめちゃってもいい気がしました。

投稿2017/02/07 03:02

編集2017/02/07 03:03
popobot

総合スコア6586

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

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

sbc

2017/02/07 03:05

入力自体不要なのでmemberテーブルの使わないフィールドは削除しましたが、member_detail側の不要なColumnまでバリデーションがかかってしまっているのはどうしたら良いでしょうか。
popobot

2017/02/07 03:09

member_detailにバリデートなんてあるんですか? 質問のコードにはなさそうですけど。 そっちも不要なら消しちゃったらどうでしょうか。
sbc

2017/02/07 04:12

申し訳ありません。記載漏れでした。MemberDetailTableのバリデーションを追記しました。 ユーザーからの入力は不要なのですが、Timestampで更新日時や作成日時を入れるようしているにもかかわらずnullチェックに引っかかってしまいます。
popobot

2017/02/07 04:48

Timestampが設定されるのはbeforeSaveなのでsave()が実行された時です。バリデートはnewEntityで実行されるので、順番的に先にバリデートです。原則ユーザが入力する値など外部からくる値はバリデートした方がいいでしょうが、内部で設定しているものについてはバリデートはいらないと思います。 逆にバグを早く見つけるという意味で、更新日時や作成日時が必須ということであればnot null制約をつけておくのはいいと思います。
sbc

2017/02/07 05:29 編集

なるほどです。 頂いたアドバイスを踏まえて、Tmplateの書き方を以下に変更し、TableのバリデーションdefaultからnotEmptyをコメントアウトしたのですが、エラー内容は変わりません。 $this->Form->hidden('created_at', ['empty' => true]);
sbc

2017/02/07 05:53

自己解決しました。 TableのバリデーションDefaultにある「->requirePresence('updated_at', 'create');」はバリデーション時に「(create時に)フィールドが存在してないといけない」というルールらしいので、これを外すことで保存出来ました。 長々とありがとうございます!
popobot

2017/02/07 06:13

遅くなってすみません。自己解決できてよかったです!!
sbc

2017/02/07 06:36

大変助かりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問