2013-03-04 8 views
6

私は複合キー(user_id、category_id)を持つmysqlテーブルを持っています。 は私がYiiコンポジットの主キーがisNewRecordである

$userCategory = new UserCategory; 
$userCategory->user_id = 1; 
$userCategory->category_id = 15; 
echo $userCategory->isNewRecord; //always true 
$userCategory->last_access = Now(); 

$userCategory->save(); 

を以下のように、これらのレコードの最後のアクセスを更新しようとしています{$ userCategory-> isNewRecord}と私はMySQLが複合主キーの重複エラーを生成)(保存しようとします。

は、私はまた、UserCategoryモデルにこれを追加しかし、助けにはならなかった

public function primaryKey() { 
     return array('user_id', 'category_id'); 
    } 

****アップデート: 混乱させて申し訳ありません。私の質問は、Yiiフレームワークの「重複キー更新」と同じ結果を得る方法です。つまり、1つのSQLクエリで挿入または更新を行う方法です。あなたはsave()

public function save($runValidation=true,$attributes=null) 
{ 
    if(!$runValidation || $this->validate($attributes)) 
     //checking if new record 
     return $this->getIsNewRecord() ? $this->insert($attributes) : $this->update($attributes);** 
    else 
     return false; 
} 
+0

該当する場合は、新しいレコードを入力するための私の回答の編集を確認してください。 – Snivs

答えて

1

のソースコードを見れば、あなたが更新しようとしている場合は、代わりに新しいものを作成するのではなく、レコードをロードする必要があります。お使いのモデルで

UserCategory::model()->findByPk(array('user_id'=> 1,'category_id '=> 15)); 
$userCategory->last_access = Now(); 
$userCategory->save(); 
+0

更新または挿入しているかどうかわかりません。私は新しいレコードでなければ挿入する必要があります。それ以外の場合は "duplicate update"と似ています。 – gadelkareem

+0

コントローラーには2つの異なる機能があり、actionUpdateで更新を処理し、actionCreateに挿入します – ShaunUK

+0

コントローラーについては言及していません!それは別のプロセスです – gadelkareem

3

、追加次の方法:上記

/** 
* Uses the primary keys set on a new record to either create or update 
* a record with those keys to have the last_access value set to the same value 
* as the current unsaved model. 
* 
* Returns the model with the updated last_access. Success can be checked by 
* examining the isNewRecord property. 
* 
* IMPORTANT: This method does not modify the existing model. 
**/ 

public function updateRecord(){ 
    $model = self::model()->findByPk(array('user_id'=>$this->user_id,'category_id'=>$this->category_id)); 

    //model is new, so create a copy with the keys set 
    if(null === $model){ 
    //we don't use clone $this as it can leave off behaviors and events 
    $model = new self; 
    $model->user_id = $this->user_id; 
    $model->category_id = $this->category_id; 
    } 

    //At this point we have a model ready for saving, 
    //and don't care if it is new or not 
    $model->last_access = $this->last_access; 
    $model->save(false); 
    return $model; 
} 

は私がやるべきことがたくさん使用し、より一般的な方法に触発されて見つける-IF-already-作成 - または - 存在するプロセス。

これを実行するには、次のコードを使用します。

$userCategory = new UserCategory; 
$userCategory->user_id = 1; 
$userCategory->category_id = 15; 
echo $userCategory->isNewRecord; //always true 
$userCategory->last_access = Now(); 

$userCategory = $userCategory->updateRecord(); 

最後の行だけがあなたのコードと異なることに注意してください。 new UserCategoryで宣言されたモデルのインスタンスが変更されていないという事実は、意図された動作です。

あなたは、モデルには、以下に保存されているか否か、あなたのコード内で確認することができます:実は、問題はisNewRecordが常に真であるならば、それはYiiのはINSERTを使用しようとしていることを意味していることである

if(!$userCategory->isNewRecord){ 
    echo 'save succeeded'; 
} 
else{ 
    echo 'save failed'; 
} 
7

ステートメントをUPDATEステートメントの代わりにデータベースに保存します。そのため、合成されていても重複したpkエラーが常に発生します。

Hereは、IsNewRecordに関する公式ドキュメントです。だから、問題はあなたが使用していることです

これを解決するには、レコードを見つけて保存する前にそれを見つけなければなりません。 )(..

見つけるレコードが見つかっ返すかNULL場合:ドキュメントも、検索の戻り値()メソッドは、その性質上多少異なるfind()方法の家族とその戻り値についてHereを読み取ることができますレコードが見つかりません。

findAll ..()は、見つかったすべてのレコードを含む配列を返します。レコードが見つからない場合は空の配列を返します。

$userCategory = UserCategory::model()->findByAttributes(array('user_id '=>1,'category_id '=>15)); 
// if user does not exist, you need to create it 
if ($userCategory == NULL) { 
    $userCategory = new UserCategory; 
    $userCategory->user_id = 1; 
    $userCategory->category_id = 15; 
} 
echo $userCategory->isNewRecord; //you will see the difference if it does exist or not exist 
$userCategory->last_access = Now(); 
$userCategory->save(); 

これは、フレームワークが正しくINSERTまたはUPDATEステートメントを使用していることを確認し、重複PKエラーます」を回避します:

あなたは主キーが存在するか天気を区別するために、この戻り値を使用することができます再取得します。

編集:新しくレコードが正しく挿入されるようにサンプルコードを拡張しました。コントローラで、その後

public function isNewRecord() 
{ 
    $result = $this->findByAttributes(array('user_id'=>$this->user_id,'category_id'=>$this->category_id)); 
    if($result === NULL) 
    { 
     return true; 
    } 
    return false; 
} 

UserCategory.php

1

$userCategory = new UserCategory; 
$userCategory->user_id = 1; 
$userCategory->category_id = 15; 
echo $userCategory->isNewRecord(); 
---- 
0

別のオプションは、親を呼び出す機能を保存保存機能の状態を変更するためにモデルを変更することです。(このコードはUserCategoryモデルに入ります)

public function save($runValidation=true,$attributes=null) { 
    $exists = UserCategory::model()->findByAttributes(array('category_id'=>$this->category_id,'user_id'=>$this->user_id)); 
    if($exists) { 
     $this->isNewRecord = false; 
    } 
    return parent::save($runValidation,$attributes); 
} 

私はちょうどテストをしました正常に動作します。あなたはこれを行うことができるはずです:あなたが他のコードを変更する必要はありませんので

$userCategory = new UserCategory; 
$userCategory->user_id = 1; 
$userCategory->category_id = 15; 
$userCategory->last_access = Now(); 
$userCategory->save(); 

は、それがレコードを見つけたかどうかのオフに基づいて、挿入または更新する必要があります。

+0

FYI beforeSave()を先に実行しようとしました。しかし、何らかの理由でsave()関数が実行されたとき、isNewRecordはtrueにリセットされました。 – Pitchinnate