RSS

Modelのcreate()とsave()時に起こる、デフォルト値設定について

19 12月

現在、cakephp 1.2での開発をしているのですが今回おやっと思う現象が。

$this->Member->create();
if($id == null){
	$id = $this->data['SubMember']['id'];
}
//SubMemberの更新
$user_list = $this->SubMember->findById($id);
$user_id =$user_list['SubMember']['user_id'];
$this->SubMember->id = $id;
if(!$this->data){	
	$this->set("user_list",$user_list);
}else{
	//変更処理
	if($this->SubMember->save($this->data['SubMember'])){
		//Userの更新
		$this->User->id = $user_id;
		$this->User->saveField('update_status', 2);
       //Memberの登録・更新
		$member_data = $this->Member->findByUserId($user_id);
		if(empty($member_data)){
		   //ないときは、新規作成なのでユーザIDをセット
			$this->data['SubMember']['user_id'] = $user_id;
		}else{
           //更新のときは更新対象の主キーをセット
			$this->Member->id = $member_data['Member']['id'];
		}
		$this->Member->save($this->data['SubMember']);
	}else{
		$this->data['SubMember']['id'] = $id;
		$this->set("user_list",$this->data);
	}
}

まあこんな感じだったのだけど、Memberの登録の時に、新規登録はいいんだけど、更新時に、このテーブルが持つuser_idが0になるという現象がおきました。更新時の流れは

$this->Member->id = $member_data['Member']['id'];
$this->Member->save($this->data['SubMember']);

こういう流れだと思うのだけど、$this->data[‘SubMember’]の中にはuser_idフィールドの入力値はない。なので通常はすでにあるレコードのuser_idはそのまま保持されると思っていた。Memberにidをセットした時点で更新対象のレコードがセットされるんだけど、save()すると、更新されるはずのないuser_idが勝手に更新され、0になるという…。なにこれ?吐き出されたSQLを見てみるとたしかにupdate対象にuser_id=0と設定されてる。え、このフィールド、更新対象に入れたつもりないよ!

不可解な現象にまったく時間をつぶしました…。このような記事をみかけて、じゃーテーブルのデフォルト値って設定したらだめなのかなあ、と単純に思っていたのだけど、じゃー他のモデルで更新してるのもことごとくだめじゃないのか?と思って他のsave()をみたけど、デフォルト値0になってる所がない。あれ、おかしいなあ、と思っていたんだけど、どうやら

$this->Member->create();

こちらとの連動っぽい。つまりcreate()したタイミングで、デフォルト値が設定(優先?)されるみたいなんだよね…。create()もしないわけにいかないので、結局デフォルト0値の設定はやめることになったんだけど、同じ状況になった人はいないのかなあーと思いまして。現在の最新版ではちがう!とかご指摘くださるとありがたいです。「こういう仕様なんだ」って思えばまあ、いいのかな…。うーん。

広告
 
5件のコメント

投稿者: : 12月 19, 2009 投稿先 cakephp

 

Modelのcreate()とsave()時に起こる、デフォルト値設定について」への5件のフィードバック

  1. cakephper

    12月 21, 2009 at 4:18 pm

    createは、APIの説明を見ると、新規にレコードを入れるときに使うと書いてるので、Update文の時は使わない方が良いですね。bakeすると、addアクションにはcreateがあって、editアクションにはcreateがないですし。
    http://api.cakephp.org/class/model#method-Modelcreate

    insertとupdateを気にしないといけないのがどうもなぁという場合は、create()の代わりに、$this->id = falseをセットするだけにしておけば良いかと。

     
    • yashio

      12月 21, 2009 at 4:57 pm

      コメントありがとうございます。
      なるほど…。save()はデータがあるときでも、ないときでも動的にその振る舞いを変えてくれるので恩恵にあずかろうと思ったのですが、
      明示的に更新なのか新規なのかを判断して処理すべきということですかね。
      $this->id = false を宣言することで、明示的にクリア、ということでしょうか。
      ありがとうございまっす!

       
      • cakephper

        12月 21, 2009 at 5:05 pm

        ちなみに$this->id = false はmodelの話なので、コントローラからやろうとするなら、
        $this->Model->id = false
        です。

        createはややこしいですね ^^; 自分もたまに間違える。。。

         
      • yashio

        12月 21, 2009 at 5:16 pm

        そうですね。やっぱり内部でちゃんとどういう動きをしてるのか、っていうのが実際の開発のときには知らないと
        結構危うい感じがしますね。ぽんぽんぽんって作れるのもフレームワークの良いところですが、最終的には
        自分用にカスタマイズしたいというか、動きをちゃんと分かってないと思ったように操縦できない、っていうのはありますね。
        まだまだ、奥が深いです…。

         

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

 
%d人のブロガーが「いいね」をつけました。