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

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

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

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

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

Q&A

解決済

1回答

2344閲覧

cakephpで1つのフォームで2つのテーブルにエンティティを保存したい

htkhtk

総合スコア8

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

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

0グッド

0クリップ

投稿2019/09/09 01:39

前提・実現したいこと

PHP(CakePHP)で1つの入力フォームから2つのテーブルにエンティティを保存するシステム作っています。
CookBookを参考にpatchEntity()でassociatedオプションを使えばできるとのことでしたがうまくいきません。

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

エラーメッセージは出ませんが、Aテーブルにはレコードが保存されるがBテーブルには保存されません。

該当のソースコード

テーブル構造

php

1ATable 2id|int(10) unsigned auto_increment|primary_key 3device_no|varchar(10) 4device_bit_no|tinyint(4) 5report_item_name|varchar(50) 6decimal_point|tinyint(4) 7display_unit|varchar(10) 8print_position_p|decimal(9,3) 9print_position_x|decimal(9,3) 10print_position_y|decimal(9,3) 11 12BTable 13id|int(10) unsigned auto_increment|primary_key 14device_no|varchar(10) 15device_bit_no|tinyint(4) 16base_valueF|decimal(12,3) 17base_valueT|decimal(12,3)

ATable.php

php

1 public function initialize(array $config) 2 { 3 parent::initialize($config); 4 5 $this->setTable('a'); 6 $this->setDisplayField('id'); 7 $this->setPrimaryKey('id'); 8 9 $this->addBehavior('Timestamp'); 10 11 $this->hasOne('B', [ 12 'foreignKey' => ['device_no', 'device_bit_no'], 13 'bindingKey' => ['device_no', 'device_bit_no'], 14 'joinType' => 'INNER' 15 ]); 16 } 17

BTable.php

php

1 public function initialize(array $config) 2 { 3 parent::initialize($config); 4 5 $this->setTable('b'); 6 $this->setDisplayField('id'); 7 $this->setPrimaryKey('id'); 8 9 $this->addBehavior('Timestamp'); 10 11 $this->belongsTo('A', [ 12 'foreignKey' => ['device_no', 'device_bit_no'], 13 'bindingKey' => ['device_no', 'device_bit_no'], 14 'joinType' => 'INNER' 15 ]); 16 17 } 18

AController.php

php

1public function add() 2 { 3 $this->loadModel('B'); 4 $a = $this->A->newEntity(['associated'=>['B']]); 5 if ($this->request->is('post','put')) { 6 $data = $this->request->getData(); 7 $a = $this->A->patchEntity($a, $data, ['associated'=>['B']]); 8 if ($this->A->save($a)) { 9 $this->Flash->success(__('登録に成功しました')); 10 11 return $this->redirect(['action' => 'index']); 12 } 13 $this->Flash->error(__('登録に失敗しました')); 14 } 15 $this->set(compact('a')); 16 }

add.ctp

php

1<script> 2 3function save(){ 4 document.MainForm.submit(); 5} 6 7</script> 8 9<div class="box_page_bg"> 10 <div class="box_main"> 11 <?php echo $this->Form->create($a, ['name'=>'MainForm', 'templates'=>'input_template']); ?> 12 <div class="box_main_table"> 13 <table> 14 <tbody id="categories"> 15 <tr> 16 <td>デバイス番号</td> 17 <td><?php echo $this->Form->control('device_no'); ?></td> 18 </tr> 19 <tr> 20 <td>デバイスビット番号</td> 21 <td><?php echo $this->Form->control('device_bit_no'); ?></td> 22 </tr> 23 <tr> 24 <td>帳票項目名称</td> 25 <td><?php echo $this->Form->control('report_item_name'); ?></td> 26 </tr> 27 <tr> 28 <td>小数点</td> 29 <td><?php echo $this->Form->control('decimal_point'); ?></td> 30 </tr> 31 <tr> 32 <td>表示単位</td> 33 <td><?php echo $this->Form->control('display_unit'); ?></td> 34 </tr> 35 <tr> 36 <td>基準値To</td> 37 <td><?php 38 $value = $a['b.base_valueT']; 39 $finalval = number_format((float)$value, 3); 40 echo $this->Form->control('b.base_valueT',['value'=>$finalval]); 41 ?></td> 42 </tr> 43 <tr> 44 <td>基準値From</td> 45 <td><?php 46 $value = $a['b.base_valueF']; 47 $finalval = number_format((float)$value, 3); 48 echo $this->Form->control('b.base_valueF',['value'=>$finalval]); 49 ?></td> 50 </tr> 51 <tr> 52 <td>印刷位置ページ</td> 53 <td><?php echo $this->Form->control('print_position_p'); ?></td> 54 </tr> 55 <tr> 56 <td>印刷位置X</td> 57 <td><?php echo $this->Form->control('print_position_x'); ?></td> 58 </tr> 59 <tr> 60 <td>印刷位置Y</td> 61 <td><?php echo $this->Form->control('print_position_y'); ?></td> 62 </tr> 63 </tbody> 64 </table> 65 </div> 66 <div class="clearfix"> 67 <div class="float_l"> 68 <a href="<?php echo SITE_URL;?>/<?php echo $controller?>/index" class="btn min color4">キャンセル</a> 69 <a href="javascript:void(0)" class="btn min color2" onclick="save()">保存</a> 70 </div> 71 </div> 72</div> 73

試したこと・気づいたこと

・print_rで変数の内容を確認
・フォームから送られたdataはBの配列を含む複合配列だった。
・patchEntity()を実行するとBの配列が消える。

$data(patchEntity前)

Array ( [device_no] => test [device_bit_no] => 0 [report_item_name] => test [decimal_point] => 0 [display_unit] => test [b] => Array ( [base_valueT] => 100.000 [base_valueF] => 10.000 [judgment_id] => 4 ) [print_position_p] => 1 [print_position_x] => 1 [print_position_y] => 1 [create_user] => 2 [modified_user] => 2 )

$a(patchEntity後)

App\Model\Entity\A Object ( [device_no] => test [device_bit_no] => 0 [report_item_name] => test [decimal_point] => 0 [display_unit] => test [print_position_p] => 1 [print_position_x] => 1 [print_position_y] => 1 [create_user] => 2 [modified_user] => 2 [[new]] => 1 [[accessible]] => Array ( [device_no] => 1 [device_bit_no] => 1 [report_item_name] => 1 [decimal_point] => 1 [display_unit] => 1 [print_position_p] => 1 [print_position_x] => 1 [print_position_y] => 1 [delete_flg] => 1 [create_user] => 1 [created] => 1 [modified_user] => 1 [modified] => 1 )

補足情報(FW/ツールのバージョンなど)

外部キーはdevice_noとdevice_bit_noの2つを使ってつなぐように言われたんですがそもそもそんなアソシエーション組めるのでしょうか?

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

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

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

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

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

nojimage

2019/09/09 02:14 編集

Entity/A.php のエンティティクラスを提示できますか?($_accessible の設定を知りたいです。)
htkhtk

2019/09/09 02:19

エンティティクラスはbakeしたまま変更してないです。 Entity/A.php ``` class A extends Entity { /** * Fields that can be mass assigned using newEntity() or patchEntity(). * * Note that when '*' is set to true, this allows all unspecified fields to * be mass assigned. For security purposes, it is advised to set '*' to false * (or remove it), and explicitly make individual fields accessible as needed. * * @var array */ protected $_accessible = [ 'device_no' => true, 'device_bit_no' => true, 'report_item_name' => true, 'decimal_point' => true, 'display_unit' => true, 'print_position_p' => true, 'print_position_x' => true, 'print_position_y' => true, 'created' => true, 'modified' => true, ]; } ``` device_no, device_bit_noはセンサーの識別番号らしいです。センサーを定義するテーブルでもあればいいと思うのですがどうも現場のセンサーエンジニア的にはこの構造がいいらしいです
guest

回答1

0

ベストアンサー

Entity/A.php の $_accessible'b' => true を追加してください。

CakePHPの、Table::newEntity/patchEntityには一括代入(Mass Assignment)攻撃に対しての保護機構があります。これはエンティティクラスの $_accessible で許可されたフィールド以外には、newEntity/patchEntity時にエンティティの値をセットしないというものです。

この機構により、フォームから送信された b のプロパティはAのエンティティにはセットされない状態となっています。

参考:
一括代入 (Mass Assignment) | エンティティー - 3.8
アクセス可能なフィールドの変更 | データの保存 - 3.8

投稿2019/09/09 03:29

nojimage

総合スコア957

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

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

nojimage

2019/09/09 03:33

単一外部キー(a_id)の場合は、bakeが対応しているので b => true が追加されていて、bakeしたエンティティがそのまま使えます。しかし、今回のように複合キーの場合は考慮されていないので、手動で追加してやる必要があります。
htkhtk

2019/09/09 06:16

すごい!できました!ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問