2013-03-04 2 views
6

У меня есть таблица mysql с составными ключами (user_id, category_id); Я пытаюсь обновить последний доступ к этим записям следующего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'); 
    } 

**** Обновление: Извините за путаницу. Мой вопрос заключается в том, как добиться того же результата, что и «ON DUPLICATE KEY UPDATE» в структуре Yii. Другими словами, как сделать вставку или обновление в одном 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

Я не знаю, обновляю ли я или вставляю. Мне нужно вставить, если это новая запись, в противном случае обновление, похожее на «на дубликат обновления» – gadelkareem

+0

Для этого есть два разных функции в вашем контроллере, обрабатывайте обновления в 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; 
} 

выше вдохновляется более общего метода, который я использую много, чтобы сделать создать или найти,-если-уже- существует процесс.

Используйте этот код для его использования.

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

На самом деле, проблема заключается в том, что если isNewRecord всегда верно, то это означает, что Yii собирается использовать INSERT вместо оператора UPDATE при сохранении модели в базе данных .. поэтому вы всегда получаете дублируемую ошибку pk, даже если она является составной.

Here является официальной документацией о IsNewRecord. Таким образом, проблема заключается в том, что вы используете

$userCategory = new UserCategory; //Always a new record, tries to INSERT 

Итак, чтобы решить это, вы должны найти запись и оценить, если он находится перед его сохранением, вместо этого. Документация также можно прочитать Here о find() семействе методов и их возврата значения, возвращаемые значения находке() методы незначительно отличаться от их характера:

найти ..() возвращает запись найдена или NULL если запись не найдена.

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 вас» re получение.

Редактировать: Усовершенствованный код примера, чтобы правильно заполнить запись, когда она новая.

1

в UserCategory.php

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

Я просто сделал тест, и мне кажется, s для правильной работы. Вы просто должны быть в состоянии сделать это:

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

Если вставить или обновить на основе прочь находит ли это запись, так что вам не придется менять какие-либо из вашего другого кода.

+0

FYI. Сначала я попытался сделать это на beforeSave(). Однако, когда функция save() запускалась по какой-либо причине, isNewRecord был сброшен на значение true. – Pitchinnate

Смежные вопросы