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

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

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

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

Q&A

解決済

1回答

5132閲覧

Cakephp3でアソシエーション使って3つのテーブルに一括入力したいです。

lovelydai

総合スコア38

CakePHP

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

0グッド

0クリップ

投稿2017/10/13 10:55

こんにちは、現在受講管理システムを作っています。
Cakephp3 のアソシエーションというものを使うと一括でできると聞いたのでマニュアルにそって試してみましたが、だめでした。POST値は正しく受け取っていますが、SaveMany()がTrueになるのにDBには何もInsertされていません。

TableはSubjectとsubject_equipment,subject_participantの3つで、DB上には関連キーは設定していません。
やりたいのは、1つのページのPOSTデータを分けて3つのテーブルに入れたいです。

SubjectTableでは以下のようにアソシエーションを設定しました。JoinTableも作りました。

Php

1class SubjectTable extends Table 2{ public function initialize(array $config) 3 { 4 parent::initialize($config); 5 6 $this->setTable('subject'); 7 $this->setDisplayField('subject_idx'); 8 $this->setPrimaryKey('subject_idx'); 9 10 $this->addBehavior('Timestamp'); 11 12 $this->belongsToMany('SubjectEquipment', ['foreignKey' => 'subject_idx', 'joinTable' => 'subject_equipment']); 13 $this->belongsToMany('SubjectParticipant', ['foreignKey' => 'subject_idx', 'joinTable' => 'subject_participant']); 14 15 }

add.ctpでは要素ごとに名前をつけておきました。データはちゃんと取れているので問題ないかと思います。

HTML

1 2<?= $this->Form->hidden('subject.subject_idx',['value' => 1]); ?> 3<?= $this->Form->multiCheckbox('subject_equipment.equipment_idx',$equipments)?> 4<?= $this->Form->control('subject_participant.participant_idx',['options' =>$participants, 'label'=>false, 'multiple' => true])?>

コントローラーに問題がありそうですがなかなか見つかりません。PatchEntityをPatchEntitiesにしたり、saveMany()をsave()に変えたりするとerrorのFlashメッセージが示されます。このコードでは、SuccessのFlashメッセージが表示されますがDBには何も起こりませんでした。

PHP

1 public function add() 2 { 3 $subject = $this->Subject->newEntity(); 4 5     if ($this->request->is('post')) { 6 $subject = $this->Subject->patchEntity($subject, $this->request->getData(),[ 7 'associated' => [ 8 'SubjectEquipment', 9 'SubjectParticipant', 10 ] 11 ]); 12 13 if ($this->Subject->saveMany($subject)) { 14 $this->Flash->success(__('The subject has been saved.')); 15 return $this->redirect(['action' => 'index']); 16 } 17 $this->Flash->error(__('The subject could not be saved. Please, try again.')); 18 } 19 $this->set(compact('subject')); 20 $this->set('_serialize', ['subject']);

アソシエーションがまだ理解できてないのもありますが、マニュアルが分かりにくく同じくしてみても動きませんでした。
どこか間違っているところがありましたら、教えていただけますでしょうか。
よろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

回答依頼が来ていたので、分かる範囲で回答しますね...

まず、コントローラ側の$this->Subject->saveMany($subject)$this->Subject->save($subject)が正しいと思います。保存しようとしてるエンティティは1つだからです。アソシエーションを一緒に保存する場合でもsave()です。

後は、テンプレート側も問題だと思います。$this->Form->control()の第一引数であるフィールド名の指定の仕方は若干ややこしいです。

  • subject.subject_idxは、subject_idxでいいはずです。subject自身であれば、subject.を指定しません。
  • subject_equipment.equipment_idxは、subject_equipments._idssubject_equipment._idsだと思います。

_idsというのはIDのリストを意味する特別な単語です
※通常、複数形なんですがモデル自体が単数形になっているので、単数形の可能性もあるかもしれません
subject_participant.participant_idxも同じような感じかと

CakePHPのマニュアルとしては、BelongsToMany アソシエーションの保存が参考になると思います。

追記
まずは、フォームの$this->request->getData()を使わず、以下の配列の値で保存できるかやってみたらどうでしょうか

$data = [ 'subject_idx' => 1, 'subject_equipments' => [ '_ids' => [1, 2, 3, 4] ] ];

投稿2017/10/16 04:51

編集2017/10/16 07:46
popobot

総合スコア6586

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

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

lovelydai

2017/10/16 04:56

誠にありがとうございます。大変参考になりました。また試してみます。
popobot

2017/10/16 05:09 編集

もしうまくいかなかったら、マニュアルのように、まずはFormを使わないで、コントローラで配列を用意して保存できるか試してみるといいかと思います。それがうまく行ったら、フォームからその配列が作れているか調べれてみてください。
lovelydai

2017/10/16 05:40

テストしてみましたら、Subjectテーブルにはデータが正しく入りますが、残り2つのテーブルには入りませんでした。これをBelongsToにすると1列だけデータが入ります。複数の選択値があるのでなかなかうまくいかないです。涙
lovelydai

2017/10/16 09:04

追記技術ありがとうございます。他の値は大丈夫でしたが、subject_equipment._idsで作られた連想配列が問題ではないかと思います。その配列に入る値は、subject_equipmentテーブルのequipment_idxフィールドに入れたいし、そのフィールドはnotEmptyで必須項目です。その配列の使い方とチェックボックスなどのMultipleFormがよく分からなくてどうすればいいのか悩んでいます。Foreachなどのループを使えばいいのか、別のオプションがあるのか、でまた色々さがしています。
lovelydai

2017/10/16 09:26

データはこのように取れています。 subject_equipment (array) _ids (array) 0 1 1 2 2 4 subject_idx 1 year 2017 customer_idx 1 creater keadmin modifier keadmin subject_participant (array) _ids (array) 0 1 1 2 subject_idx 1 year 2017 customer_idx 1 creater keadmin modifier keadmin あの_idsの配列にあるデータをそれぞれのテーブルの名前‗idxフィールドに入れるとうまく行けそうな気がしますがどうすればいいのかまったく気がつきません。またアドバイスいただければ幸いです。よろしくお願いいたします。
lovelydai

2017/10/16 10:19

何度もすみません。同じコードでbelongsToに変えて動かしてみたら、配列の中で1番目のデータはテーブルにInsertされました。この場合、equipment_idxフィールドはNULLでした。どうしてもあの_ids配列が問題で、その値をなんとかしてequipment_idxに入れるとよさそうですが…
popobot

2017/10/16 11:49

まず、subject_equipmentをsubject_equipmentsに変えてやってみてください。最後にsがついていて複数形です。belongsToは1つなので単数形で、belongsToManyは複数なので複数形です。 あと、NULLになっている問題ですが、Table側のアソシエーションの設定が正しくないからかもしれません 以下のマニュアルにオプションがあります。 https://book.cakephp.org/3.0/ja/orm/associations.html bindingKeyやtargetForeignKeyにequipment_idxを指定する必要がありそうですね
popobot

2017/10/16 11:54

ちなみに、テーブル名やカラム名はなるべくCakePHPの規約に則ったほうが、設定が少なくてすみますし、ハマることも減ります。今からでも変更できるのであれば、そこから直した方が早いかもしれません https://book.cakephp.org/3.0/ja/intro/conventions.html#model-and-database-conventions ※もちろん、規約にそってなくても正しく設定すれば動きますけど
lovelydai

2017/10/17 02:04

icchiiさん、本当にありがとうございます。しかし、教えていただいたこと試してみましたが、まだうまくできません。DebugのSQLを見ると、subject_equipmentテーブルへのInsert文自体がでてきません。また、ひとつ気になったのが、今私がやりたいのは2つのbelongsToManyをひとつのpatchEntityとsaveで処理しようとするのがそもそもダメかも知らないと思いました。そこでequipmentだけ試してみましたがこれもダメでした。 時間も限られているし、自分の知識が足りないということでまずはSQLBuilderを使って一つ一つ入れることにしてみようと思っています。この件は今後やり直してみます。またアドバイスいただければと思います。ありがとうございます。
popobot

2017/10/17 03:04

> ひとつ気になったのが、今私がやりたいのは2つのbelongsToManyをひとつのpatchEntityとsaveで処理しようとするのがそもそもダメかも知らないと思いました。 そんなことはないです、自分は10個以上のアソシエーションを含むエンティティをひとつのpatchEntityとsaveで処理しています。 > 時間も限られているし、自分の知識が足りないということでまずはSQLBuilderを使って一つ一つ入れることにしてみようと思っています。 そうですね、わりとこの辺の処理は難易度高いので、一旦別の方法で実装するのはいいと思いました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問