2011-11-29 27 views
5

私はのyiiアクティブレコードを使用しています。同じテーブルの主キーに追加する必要があるフィールドがあるテーブルがあります。プライマリキーは自動インクリメントフィールドなので、保存する前にプライマリキーにアクセスできません。
同じテーブルの別のフィールドに自動インクリメントプライマリキーを追加するにはどうすればよいですか?

$model->append_field = "xyz".$model->id; // nothing is appending 
$model->save(); 
$model->append_field = "xyz".$model->id; //id is now available 

どうすればよいですか?
私は挿入直後に更新できることを知っていますが、より良い方法がありますか?

答えて

3

INSERTステートメントの実行後、レコードにはidしか割り当てられません。 idがINSERTの前にあるかどうかを判断する方法がないので、は、INSERT後に連結されたフィールド値でUPDATEを実行する必要があります。

これを行うためにストアドプロシージャまたはトリガをMySQLに書き込むことができます。これにより、アプリは1つのSQL文を実行してこれを実行します。ただし、ロジックをMySQLに移行するだけで、最後にINSERTとUPDATEの両方が発生しています。

3

いくつかのより多くの回避策:

これはほとんどあなたのアプローチである。)

$model->save(); 
$model->append_field = "xyz".$model->id; //id is now available 
$model->save(); 

しかし、あなたは、あなたがしたいことに注意して、カスタムafterSave()メソッドで行動にこの機能を移動することができますイベントをループしないように気をつけなければなりません。

それともそれ

function getFull_append_field(){ 
    return $this->append_field.$this->id; 
} 

のgetterを書くが、あなたはCONCAT()または同様のものであり、属性を作成しない限り、あなたは、SQL文では使用できません。 (@schmunkで述べたように)にしたループイベントを回避するために

//in the model class 
class SomeModel extends CActiveRecord{ 
    ... 
    protected function afterSave(){ 
    parent::afterSave(); 
    if($this->getIsNewRecord()){ 
     $this->append_field=$this->append_field.$this->id; 
     $this->updateByPk($this->id, array('append_field'=>$this->append_field)); 
    } 
    } 
} 

一つの方法:

+0

+1私は '$ model-> save()'を前にやっていましたが、今はafterSave()を使っています。また、私がconcat()のために見たすべての例は、selectではなくinsertでしか使用しないので、とにかく2つのSQL呼び出しを作成しています。 –

2

私はそれを実装する方法この質問に来る誰にも正確に興味があるかもしれないが、ので、ここでのコードですafterSave()メソッド内でsaveAttributes(...)を使用しますが、saveAttributes(...)はisNewRecordをチェックし、新しいレコードである場合にのみ値を挿入するため、saveAttributes(...)を呼び出す前にsetNewRecord(false);を使用する必要があります。
saveAttributes(...)が実際にupdateByPk(...)を呼び出すので、私は直接updateByPk(...)自体を使用しました。

関連する問題