これは平成最後の月。
CakePHP2.x系。入力チェックが通らないたび、フォームの内容が編集前に戻ってしまう不具合を直したときの話。
単純にまず、DBがイケてなかったんです。
INT id
INT type
VARCHAR(255) value
どこからどう見てもEAV。Entity Attribute Value。
何故よくないかのDB設計理論的な難しい説明は置いとく。
DB構造はその時動かす権限がなかった。(もし権限があったらその根本原因から直してしまいたかった)
で、その不具合が発生している画面を見て。
・DBから持ってきたデータ構造
・フォームへ渡すときのデータ構造
・フォームの初期値を表示するとき
これらが全部バラバラで往生した…。
DBからとってきたときの配列:
[
0=> ['Model'=> [id => 1, type => 1, value => 5]],
1=> ['Model'=> [id => 2, type => 2, value => "someaddress@example.com"]],
2=> ['Model'=> [id => 3, type => 2, value => "anotheraddress@example.com"]]
]
これを加工して,typeをキーにしてビューに渡すけれど:
[
1=> [
0=> ['id'=>1, 'value'=>5]
],
2=> [
0=> ['id'=>2, 'value"=>"someaddress@example.com"],
1=> ['id'=>3, 'value'=>"anotheraddress@example.com"]
]
]
ビューでさらに取り出す:
(Formヘルパに’value’で渡している)
$this->Form->input('Model.type_1.value',['type'=>'text', 'value'=> $this->request->data[1][0]['value']);
$this->Form->input('Model.type_2.0.value,['type'=>'text', 'value'=>$this->request->data[2][0]['value']]);
$this->Form->input('Model.type_2.1.value,['type'=>'text', 'value'=>$this->request->data[2][1]['value']]);
(あと、idをそれぞれhiddenフォームで送っていたりする)
フォームを送信すると、入ってくるのは…
[
'Model'=> [
'type_1'=> ['id'=> 1, 'value'=>5],
'type_2'=> [
0=> ['id'=> 2, 'value'=> 'someaddress@example.com],
1=> ['id'=> 3, 'value'=> 'anotheraddress@example.com]]
]
]
]
当然、DBからデータを取ってきたときとも最初フォームに渡したときとも違う構造。
このままではフォームの次の値が取れないから、前のコードではリクエスト関係なくDBからその都度データ読み込んで来ていた。
エラー値ならエラー値のままフォームに残しておく仕様なのに…。
とりあえず、その時はビューに渡すときの構造と受け取る時のデータ構造をそろえた。
(そうでないと変換が双方向に必要になるんで)
そろえれば使えなくはない。
Formヘルパに渡すvalue要素も要らなくなるし、入力チェックが通らないときフォームの初期値を作るためだけにDBを読みに行かなくていい。
でも、それでもやっぱりEAVはイケてない…。
この構造の時、まず絶対に1つしかないパラメータをこう…ひとつテーブルにして
INT model_id
INT type1_val
で、複数登録する必要がありそうな情報だけテーブルを分けてこう…。
INT model_mail_id
VARCHAR type2_mail
そしたら、DBからとってきた構造をパースしてフォームに渡す必要って本来それほどないはずなんです…。
僕がDB設計するときには、後輩に同じような愚痴を語らせないためにも、
あと、DB設計理論以上にそもそもコーディングがめちゃくちゃ往生するので、できることならEAVは避けていきたいという話でした。