CakePHPのFormHelperのGETメソッドとPOSTメソッドの違いではまった件
プルダウンやラジオボタン、チェックボックスと、テキスト入力を組み合わせた、ちょっと複雑な検索画面を作っている時にはまりました。
ほとんど、フォームの入力値をAND検索するだけだったのでpostConditions()を使って作ってました。
検索画面なのでGETメソッドでと思って変更したら、生成されたinput要素のname属性のフォーマットが変わってしまい、postConditions()が使えない形になってしまいました。
確かに"post"Conditions()ってメソッドだけど、FormHelperの方がGETメソッドとPOSTメソッドで動きを変えるとは予想していませんでした。
一応、無理やりな回避策を書いてみましたが、正攻法や良い方法を知ってる人がいたら教えてほしいです。
POSTメソッドの場合
<?php $this->Form->create(array('type'=>'post')); echo $this->Form->input('ModelA.foo'); echo $this->Form->input('ModelB.bar'); echo $this->Form->input('ModelA.ModelB.baz'); echo $this->Form->input('ModelA.ModelB.ModelC.qux'); echo $this->Form->input('ModelA.ModelB.ModelC.ModelD.quux');
<div class="input text"> <label for="ModelAFoo">Foo</label> <input name="data[ModelA][foo]" type="text" id="ModelAFoo" /> </div> <div class="input text"> <label for="ModelBBar">Bar</label> <input name="data[ModelB][bar]" type="text" id="ModelBBar" /> </div> <div class="input text"> <label for="ModelAModelBBaz">Baz</label> <input name="data[ModelA][ModelB][baz]" type="text" id="ModelAModelBBaz" /> </div> <div class="input text"> <label for="ModelAModelBModelCQux">Qux</label> <input name="data[ModelA][ModelB][ModelC][qux]" type="text" id="ModelAModelBModelCQux" /> </div> <div class="input text"> <label for="ModelAModelBModelCModelDQuux">Quux</label> <input name="data[ModelA][ModelB][ModelC][ModelD][quux]" type="text" id="ModelAModelBModelCModelDQuux" /> </div>
POSTメソッドの場合、name属性は data[Model][field] の様なフォーマットで生成されます。
data[ModelA][ModelB][baz] の様に、アソシエーションの表現も出来ます。
GETメソッドの場合
<?php $this->Form->create(array('type'=>'get')); echo $this->Form->input('ModelA.foo'); echo $this->Form->input('ModelB.bar'); echo $this->Form->input('ModelA.ModelB.baz'); echo $this->Form->input('ModelA.ModelB.ModelC.qux'); echo $this->Form->input('ModelA.ModelB.ModelC.ModelD.quux');
<div class="input text"> <label for="ModelAFoo">Foo</label> <input name="foo" type="text" id="ModelAFoo" /> </div> <div class="input text"> <label for="ModelBBar">Bar</label> <input name="bar" type="text" id="ModelBBar" /> </div> <div class="input text"> <label for="ModelAModelBBaz">Baz</label> <input name="ModelB[baz]" type="text" id="ModelAModelBBaz" /> </div> <div class="input text"> <label for="ModelAModelBModelCQux">Qux</label> <input name="ModelC[qux]" type="text" id="ModelAModelBModelCQux" /> </div> <div class="input text"> <label for="ModelAModelBModelCModelDQuux">Quux</label> <input name="" type="text" id="ModelAModelBModelCModelDQuux" /> </div>
GETメソッドにした場合、モデル名を書いても無視されて foo や bar のみになります。
当然アソシエーションの表現も出来ませんが、モデルを2〜3個並べた場合のみ、若干POSTメソッドの時と似た出力です。
ただ4個以上のモデルを並べたら、空文字になってしまったので、モデル名を書く事自体が想定外なんでしょう。
回避策
<?php $this->Form->create(array('type'=>'get')); echo $this->Form->input('data[ModelA][foo]'); echo $this->Form->input('data[ModelB][bar]'); echo $this->Form->input('data[ModelA][ModelB][baz]'); echo $this->Form->input('data[ModelA][ModelB][ModelC][qux]'); echo $this->Form->input('data[ModelA][ModelB][ModelC][ModelD][quux]');
<div class="input text"> <label for="JobofferData[ModelA][foo]">Data[model A][foo]</label> <input name="data[ModelA][foo]" type="text" id="JobofferData[ModelA][foo]" /> </div> <div class="input text"> <label for="JobofferData[ModelB][bar]">Data[model B][bar]</label> <input name="data[ModelB][bar]" type="text" id="JobofferData[ModelB][bar]" /> </div> <div class="input text"> <label for="JobofferData[ModelA][ModelB][baz]">Data[model A][model B][baz]</label> <input name="data[ModelA][ModelB][baz]" type="text" id="JobofferData[ModelA][ModelB][baz]" /> </div> <div class="input text"> <label for="JobofferData[ModelA][ModelB][ModelC][qux]">Data[model A][model B][model C][qux]</label> <input name="data[ModelA][ModelB][ModelC][qux]" type="text" id="JobofferData[ModelA][ModelB][ModelC][qux]" /> </div> <div class="input text"> <label for="JobofferData[ModelA][ModelB][ModelC][ModelD][quux]">Data[model A][model B][model C][model D][quux]</label> <input name="data[ModelA][ModelB][ModelC][ModelD][quux]" type="text" id="JobofferData[ModelA][ModelB][ModelC][ModelD][quux]" /> </div>
すごい無理やり感がありますが、これで何とかなります。
あまりバッドノウハウは使いたくないんですけどね・・・
$this->data と同じような配列が $this->params['url']['data'] に格納されます。
<?php echo $this->Form->input('data[ModelA][foo]', array('multiple'=>'checkbox', 'options'=>$fooArray, 'label'=>'Foo'));
この方法でチェックボックスの様な配列になる入力も、GETメソッドで送信できました。
ラベルがひどい事になっちゃうので、label オプションは漏れなく設定した方がよさそうです。
postConditions()とは
フォームから送られてきたデータを、モデルのfindなどの検索条件 conditions の形に変換してくれる Controller->postConditions() という便利なメソッドがあります。
<?php Array ( [Model] => Array ( [foo] => bar [baz] => qux [quux] => Array ( [0] => corge [1] => grault ) ) )
POSTされたデータはこんな配列としてコントローラーの $this->data に入ってます。
$this->postConditions($this->data)
<?php Array ( [Model.foo] => bar [Model.bar] => qux [Model.quux] => Array ( [0] => corge [1] => grault ) )
postConditions() でこのような Model->find() の conditions オプションとして使える配列に作り直してくれます。