CakePHPで複数レコードを一括でバリデーションをかけて一括で保存する方法

2014年05月10日(土)
さぁ、今回もCakePHPのお話にしましょう。CakePHPで一括saveする際にバリデーションチェックの有無を引数により制御できるのですが、結構バリデーションをかけるタイミングを変えたいシュチュエーションが発生することが多かったのでおさらいしてみましょう。
また、複数レコードの場合は配列マジックが結構するどいので注意する点が多かったので自らのリマインドも含めて。
CakePHPで複数レコードを保存する方法はどうやるの?
CakePHPの「saveAll」関数を使おう!
全然知らない人はCakePHPでのsave関数形は以下を参照してみよう!
http://book.cakephp.org/2.0/ja/models/saving-your-data.html
saveAll関数に渡す配列の形式は?
これも結構つまずきやすい個所ですよね?
僕は何回もつまずきましたよ・・・これがCakePHPの配列マジックですよね。。。
saveAllに渡す配列は以下の形式で行おう $data = array( 'User' => array( 0 => array( 'name' => 'foo', 'age' => 25 ), 1 => array( 'name' => 'bar', 'age' => 26 ) ) );
こんな感じに配列を整理してsaveAll関数に渡してやればとりあえずOKですぞい。
View側でPOSTする場合のFromの組み方
複数のレコードをView側より受け取ってごにょごにょ・・・とかいう処理も多いですよね。
その場合はView側でFromヘルパーを用いて対応することができます。
$this->Form->input( 'User.0.name' ); $this->Form->input( 'User.0.age' ); $this->Form->input( 'User.1.name' ); $this->Form->input( 'User.1.age' );
こんな感じでっしゃろ。
なんとなく配列の形式がイメージできるような感じなのでわかりますよね?
この例は固定値で0,1,2・・・とやっていますが、動的に複数レコードを生成する感じにしたい場合はfor文とかで0,1・・・の部分に変数を定義してあげればいいですね。
ControllerでPOST値を取得
先ほどのView側のFormよりPOST値を取得できます。
そのPOST値の中身を見ると一番最初に書いた配列構造となっていると思います。
debug( $this->request->data );
とかで中身を取得できると思います。
saveAllする際はモデル名まで指定する
saveAllするときはモデル名まで指定
$this->User->saveAll( $this->request->data['User'] );
こんな感じで。指定しないとうまく保存できないので注意。
これでうまく複数レコードを保存または更新できると思います。それと同時にバリデーションもチェックしてくれています。
だがしかし、今回は任意にバリデーションをかけるということでしたので、まだ続きます。
saveAllでバリデーションチェックのみする
更新や登録をしないでバリデーションチェックのみを行いたい場合等もなかにはあると思います。確認画面とか確認画面とか。。
その際には同じsaveAllで引数をコントロールすることでできます。
$this->User->saveAll( $this->request->data['User'], array( 'validate' => 'only' ) );
こんな感じで。
まぁ、第二引数に
array( 'validate' => 'only' )
を付与することによってバリデーションチェックのみを行うようになります。
任意のパラメータを配列に含む場合は要チェック
つまりね。配列マジックにはまるんだよこれが。
僕がつまずいたのは以下のパターンでつまずきました。これは正常にできないっぽいです。
$data = array( 'User' => array( 'check' => '1', // これはイカンぜよ!! 0 => array( 'name' => 'foo', 'age' => 25 ), 1 => array( 'name' => 'bar', 'age' => 26 ) ) );
こんな感じで配列構造が意図していない形になってしまうとアウトなようです。
任意のパラメータを渡したい場合はモデル配列の外で指定しましょう。
安西先生…検索で取得した配列をsaveAll配列にしたいです…
これはきちんとモデルのbelongsToとかhasManyとかを設定していれば問題ないはずなんですが、特に指定していない場合は厄介になるはずです。
どうしても設定したくない人っているもんね。
そんなときはCakePHPには配列をいろいろいじれるたくましい関数があるので勉強してみてもよいと思います。
Set::map( $data )
とかね。
しかしSet関数にかわり、CakePHP2系ではHash関数が用意されているので、Hash関数を使いましょう。
この編はドキュメントを見て自分でいいものを見つけて判断していくのがよいでしょう。
では、今回もこの辺で失礼するでござる。