7

複合キー ( user_id 、 category_id ) を持つ mysql テーブルがあります。これらのレコードの最終アクセスを次のように更新しようとしています

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

$userCategory->save();

{$userCategory->isNewRecord} で、save() を実行しようとすると、MySQL が複合主キーの重複エラーを生成します。

これも UserCategory モデルに追加しましたが、役に立ちませんでした

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

****更新: 混乱して申し訳ありません。私の質問は、Yii フレームワークで「ON DUPLICATE KEY UPDATE」と同じ結果を得る方法です。つまり、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;
}
4

5 に答える 5

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;
}

上記は、私が頻繁に使用する、「すでに存在する場合の作成または検索」プロセスを実行する、より一般的な方法に触発されています。

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

$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変更されていないという事実は、意図された動作です。

次に、モデルが次のように保存されているかどうかをコードで確認できます。

if(!$userCategory->isNewRecord){
  echo 'save succeeded';
}
else{
  echo 'save failed';
}
于 2013-03-07T15:35:27.800 に答える
1

更新しようとしている場合は、新しいレコードを作成するのではなく、レコードをロードする必要があります。

UserCategory::model()->findByPk(array('user_id'=> 1,'category_id '=> 15));
$userCategory->last_access = Now();
$userCategory->save();
于 2013-03-04T13:04:18.047 に答える
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();

レコードが見つかったかどうかに基づいて挿入または更新する必要があるため、他のコードを変更する必要はありません。

于 2013-03-08T15:38:20.670 に答える