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

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

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

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

3回答

12675閲覧

動的に追加したフォームに入力されたデータがPostされない

KensukeNoda

総合スコア11

CakePHP

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2016/02/08 08:30

編集2016/02/08 12:00

CakePHP ver2.7.5にて、編集画面に「フォームを動的に追加して一括保存する機能」を追加したいと考えています。

そこで動的にフォームを追加するスクリプトを組み、フォームの生成も動作しました。しかし、Controllerに引き渡されている配列を確認すると、動的に追加したフォームのデータが配列に格納されていませんでした。

原因につきまして、ご教示のほどお願い致します。

(画面イメージ)

カラム1 | カラム2 | 削除ボタン
データ | データ | [削除] ・・・DBから取得
データ | データ | [削除] ・・・同上
データ | データ | [削除] ・・・同上


[追加ボタン] ・・・最終行にフォームを追加

[保存ボタン] ・・・データをPostする(データの更新、新規作成処理)

(受け渡される配列のイメージ)

※Controllerでdebug($this->request->data)した結果
※(int)12 ~ 14は元々DBに格納されていたデータです。

array(

'TestDetail' => array( (int) 12 => array( 'id' => '12', 'title' => 'test1-1', 'content' => '' ), (int) 13 => array( 'id' => '13', 'title' => 'test1-2', 'content' => '' ), (int) 14 => array( 'id' => '14', 'title' => 'test1-3', 'content' => '' ), new1 => array( 'id' => '14', 'title' => 'test1-3', 'content' => '' ),

(実際に受け渡される配列のイメージ)

array(

'TestDetail' => array( (int) 12 => array( 'id' => '12', 'title' => 'test1-1', 'content' => '' ), (int) 13 => array( 'id' => '13', 'title' => 'test1-2', 'content' => '' ), (int) 14 => array( 'id' => '14', 'title' => 'test1-3', 'content' => '' ) )

・view(中略)

PHP

1<tbody> 2 <?php foreach ($datas as $data): ?> 3 <tr> 4 <?php 5 $id = intval($data['TestDetail']['id']); 6 $target_id = "data[TestDetail][".$id."]"; 7 ?> 8<td class="col-xs-3"> 9 <input type="hidden" <?php echo 'name='.$target_id.'[id] value='.$data['TestDetail']['id'] ?> > 10 <input type="text" <?php echo 'name='.$target_id.'[title] value='.$data['TestDetail']['title'] ?>> 11</td> 12<td class="col-xs-7" style="text-align:left"> 13 <input type="text" <?php echo 'name='.$target_id.'[content] value='.$data['TestDetail']['content'] ?>> 14</td> 15<td class="col-xs-2"> 16 <button class="btn btn-default" type="button"> 17 削除 18 </button> 19</td> 20</tr> 21<?php endforeach;?> 22</tbody> 23 24</table> 25<!--行追加ボタン--> 26 <button class="btn btn-primary" type="button" id="rowAdd">追加</button>

・行追加ボタンのスクリプト

JavaScript

1<script> 2$(document).ready ( function() { 3 var index = 0; 4 5 $('#rowAdd').click(function() { 6 index ++; 7 var $newTitle = "<td class='col-xs-3'><input type='text' name='data[TestDetail][newData"+index+"][title]'></td>"; 8 var $newContent = "<td class='col-xs-7'><input type='text' name='data[TestDetail][newData"+index+"][content]'></td>"; 9 var $newRemove = "<td class='col-xs-2 remove'><button class='btn btn-default' type='button'>削除</button></td>"; 10 var $newRow = "<tr>"+$newTitle+$newContent+$newRemove+"</tr>"; 11 12 // 最後の行に追加 13 $('#target').append($newRow); 14 $('#target tr:last').hide().fadeIn(500); 15 }); 16 }); 17 18 /* 追加した行を削除 */ 19 $(document).on('click','.remove',function () { 20 $(this).parent().fadeOut('slow',function(){$(this).remove();}); 21 }); 22</script>

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

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

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

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

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

guest

回答3

0

入力ミスかもしれませんが、viewの6行目

$target_id = "data[TestDetail][".$id."]";

dataではなく、$dataでは?

投稿2016/02/08 15:21

twin_bird

総合スコア230

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

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

shi_ue

2016/02/09 04:04

横槍すみません。 いやいや、dataであってますよ。これはnameアトリビュートをCakePHPの認識する名前にしようとしようとしているだけです。
KensukeNoda

2016/02/09 04:47

ご指摘ありがとうございます。 shi_ueさんのおっしゃる通り、$target_idはnameで使っているもので、ご指摘の箇所は正常に動作しております。とはいえ、変数名が抽象的で可読性が低いので、見直した方が良さそうですね。
guest

0

ベストアンサー

色々検証してみました。
この配列的な書き方は、別段CakePHPの仕様じゃないんですね。勉強不足でした。
PHPはこの形でPOSTされると、配列に分解するんですね。

それで、KensukeNodaさんのスクリプトを元にローカルでテストしてみました。
しかし、ちゃんと値は受け取れるようです。

print_r($_POST)の結果です。

TEXT

1Array 2( 3 [data] => Array 4 ( 5 [TestDetail] => Array 6 ( 7 [12] => Array 8 ( 9 [id] => 12 10 [title] => test1-1 11 [content] => 12 ) 13 14 [13] => Array 15 ( 16 [id] => 13 17 [title] => test1-2 18 [content] => 19 ) 20 21 [14] => Array 22 ( 23 [id] => 14 24 [title] => test1-3 25 [content] => 26 ) 27 28 [newData1] => Array 29 ( 30 [title] => test-4 31 [content] => t 32 ) 33 34 [newData2] => Array 35 ( 36 [title] => test-5 37 [content] => aa 38 ) 39 40 ) 41 42 ) 43 44)

ですので、見た目はformの中に要素を追加しているように見えますが、実はformの外側に要素を追加していたりして、POSTする際に実際に送れていないんじゃないでしょうか?(そこまでは提供のコードでは分かりませんでした)

ブラウザの開発ツールなどで追加した要素の位置を見てみてください。

投稿2016/02/09 06:48

shi_ue

総合スコア4437

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

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

KensukeNoda

2016/02/09 07:52

検証までしていただいて、ありがとうございます。 原因はformタグの位置でした。formタグの開始位置と閉じる位置がずれていたので統一させたところ、更新・新規ともに配列が受け渡されました。
guest

0

新しい要素を追加するときに、

Javascript

1var $newTitle = "<td class='col-xs-3'>"++ 2 "<input type='text' name='data[TestDetail][newData"+index+"][title]'>"+ 3 "</td>";

としていますが、これだとCakePHPでは認識できないのでは?
data[TextDetail][数値][title]とならなければならないと思います。

なので、12~14以外の数値を入れてPOSTするしかないと思いますが、それだとどれが新しく追加したデータか分からないと思いますよ。

Javascript

1var $newTitle = "<td class='col-xs-3'>"+ 2 "<input type='text' name='data[NewTestDetail]["+index+"][title]'></td>";

こんな風に別のオブジェクトを作ってしまって、CakePHP側で処理を入れた方がいいと思います。

投稿2016/02/09 04:17

shi_ue

総合スコア4437

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

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

KensukeNoda

2016/02/09 05:23 編集

ご回答いただきありがとうございます。 確かに、その方がContorollerで「更新」と「新規登録」を分岐させる上でも、オブジェクトを分けた方がスマートに処理できますね。 ただ、今のところ、オブジェクトを分けてもNewTestDetailは認識されていません。 別の箇所にもバグがありそうです。 ちなみに、[NewTestDetail]は配列の要素名というだけで、オブジェクトの宣言等は必要ない、との認識で間違いないでしょうか? (追記・備忘) 保存した際にControllerでdebug($this->request->data['NewTestDetail'])で確認したところ、[Undefined index: NewTestDetail]のエラーが出ていました。NewTestDetailモデルを作った上で、loadModelをすれば認識するかと思いきや出来ませんでした。 (さらに追記) 更新したデータ(data[OldTestDetail])と新たに追加したデータ(data[NewTestDetail])でオブジェクトを分けてPostしてみました。 oldTestDetail → 認識される newTestDetail → 認識されない newTestDetailがoldTestDetailと同じ<form>タグ内の要素として認識されていない、ということかなと考えています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問