CakePHP - переход от вставки к обновлению в Model-> beforeSave () - PullRequest
4 голосов
/ 19 апреля 2011

Вот моя функция beforeSave.checkExisting () проверяет, являются ли некоторые поля в $ this-> data уникальными, и возвращает false, если записи не существует, или идентификатор существующей записи, если она существует.Эта функция работает нормально.

    public function beforeSave(){
    if ($this->checkExisting() !== false){
        $this->id = $this->checkExisting();
    }
    return true;
}

Я думаю, что мой код должен сделать следующее: если существует существующая запись, установите Model-> id для идентификатора этой существующей записи, и, таким образом, форсируйте CakePHPобновлять вместо вставки.

Что этот код на самом деле делает, так это вставлять новую запись.

Если я изменяю $ this-> id = $ this-> checkExisting ();$ this-> data ['Model'] ['id'] = $ this-> checkExisting () ;, MySQL выдает ошибку (дублирующее значение для первичного ключа), поскольку Cake все еще пытается вставить, а не обновить, data.

На каком этапе Cake решает сделать вставку, а не обновление?BeforeSave () слишком поздно, чтобы повлиять на это решение?

Редактировать - вот мой код контроллера:

public function add(){
    if (!empty($this->data)){
        $saved = 0;
        foreach($this->data['Attendance'] as $att){
            $this->Attendance->create();
            if ($this->Attendance->save(array('Attendance'=>$att))){
                $saved++;
            }
            if ($saved > 0){
                $this->Session->setFlash('Data saved successfully','success');
            }else{
                $this->Session->setFlash('No data was saved.  Please make sure you have entered some data.','failure');
            }
        }
    }
}

Подумайте, это как-то связано с тем, что я явно вызываю Attendance?:: создать ()

Ответы [ 3 ]

2 голосов
/ 19 апреля 2011

Нет, до сохранения еще не поздно это изменить.Model-> save () выполняет следующие действия по порядку:

  1. Вызов Model-> set () с передачей предоставленных данных.Это извлекает идентификатор и устанавливает Model-> id
  2. Вызывает функции обратного вызова (включая beforeSave ())
  3. Решает, обновлять или вставлять, основываясь на установленном Model-> id

Ваш код выше должен работать при условии, что checkExisting () работает правильно.Я хотел бы еще раз взглянуть на ваш код checkExisting ().

Также обратите внимание, что ваш код неэффективен при двух вызовах checkExisting ().Это было бы лучше:

$existing = $this->checkExisting();
if($existing) {
    $this->id = $existing;
}

Редактировать Я предполагаю, что вы создали checkExisting (), потому что ваше действие add () завершает сохранение набора частичных записей, если один иззаписи недействительны.Вы должны использовать saveAll (), который может проверить все записи перед сохранением любой из них.

public function add() {
    if(!empty($this->data)) {
        if($this->Attendance->saveAll($this->data)) {
            $this->Session->setFlash('Data saved successfully','success');
        } else {
            $this->Session->setFlash('No data was saved.  Please make sure you have entered some data.','failure');
        }
    }
}
2 голосов
/ 12 марта 2012

Если ваш код или код Тайлера работают, это должно быть какое-то чудо.Когда beforeSave вызывается, Cake уже сделал запрос, чтобы узнать, существует ли набор записей и требуется ли обновление или вставка в противном случае.Нет способа, которым вы можете перейти на Обновление в beforeSave.Одним из возможных решений является удаление набора записей, если он существует:

public function beforeSave() {
    $existing = $this->checkExisting();
    if($existing) {
        $this->id = $existing;
        $this->delete();
    }
    return true;
}
0 голосов
/ 19 апреля 2011

Есть ли что-то, что вы делаете, что позволяет пользователю отправлять форму без необходимости ID? Обычно, если пользователь редактирует запись, у вас уже должен быть идентификатор, и вам не нужно проверять его при отправке формы. Затем функция в контроллере отправит запись с прикрепленным идентификатором, сообщая модели, что это ОБНОВЛЕНИЕ, а не СОХРАНЕНИЕ.

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

...