обновление / вставка метода сохранения доктрины на основе уникального поля - PullRequest
3 голосов
/ 30 марта 2010

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

Я предполагаю, что preSave был бы подходящим вариантом, если preSave () выполняется автоматически с помощью save (), если он присутствует.

columns:
  email:
    type: string(255)
    unique: true
    email: true

Мне нужно save (), чтобы проверить, задан ли файл как уникальный если это так, чтобы проверить, являются ли данные поля в этом случае адресом электронной почты уникальным. На основании этой информации решите вставить или обновить опубликованные поля, которые изменились.

Ответы [ 6 ]

1 голос
/ 31 января 2011

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

public function  preInsert($event) {
    if ($this->state() == Doctrine_Record::STATE_TDIRTY) {
            $r == findRecordInDatabaseUsingThis();
            $this->assignIdentifier($r->id);
            $this->refresh();
            $this->state(Doctrine_Record::STATE_CLEAN); // STATE_DIRTY to do an update, this will just use the existing record without updating
            $event->skipOperation();
        }
    }
}
0 голосов
/ 27 марта 2012

Я знаю, что немного опоздал, но я нашел этот пост в Google, когда пытался обновить поле в хуке PreInsert. Я не смог этого сделать, следуя тому, что ты сделал, поскольку твоя цель - обновить Doctrine-Record, а не обновить его в БД (насколько я понимаю ^^)

Чтобы выполнить обновление в БД, мне пришлось использовать следующий код (я был удивлен, что мне пришлось снова вызывать «сохранить»)

public function preInsert(Doctrine_Event $event)
{
    /* @var $weighSameDate Doctrine_Collection */
    $weighSameDate = Doctrine::getTable('BiometryWeightData')
        ->createQuery()
        ->where('user_id=?', $this->getUserId())
        ->where('date=?', $this->getDate())
        ->execute();
    if (count($weighSameDate)) {
        /* @var $weight BiometryWeightData */
        $weight = $weighSameDate->getFirst();
        if ($weight->getWeight() != $this->getWeight()) {
            $previous = clone $this;
            $this->assignIdentifier($weight->getId());
            $this->hydrate($weight->toArray());
            $this->setWeight($previous->getWeight());

            $this->state(Doctrine_Record::STATE_DIRTY); // STATE_DIRTY to do an update
            $this->save();
        }
        $event->skipOperation();
        return;
    }
    parent::preInsert($event);
}
0 голосов
/ 20 июля 2011

Я только что откопал этот вопрос после столкновения с подобной ситуацией. @ Ответ Питера - почти то, что я искал, но я добавил пару изменений.

/**
 * Check if identical record exists before (re)inserting
 * @param \Doctrine_Event $event
 * @return void
 */
public function preInsert(\Doctrine_Event $event)
{
    $existing = $this->getTable()->findOneBy('email', $this->email);
    if ($existing) {
        $this->assignIdentifier($existing->id);
        $this->hydrate($existing->toArray());
        $this->state(self::STATE_CLEAN);
        $event->skipOperation();
    }
}

Использование hydrate() вместо refresh() означает, что вы выполняете на 1 запрос SELECT меньше.

Я знаю, что у вас, вероятно, есть ответ на эту проблему (по крайней мере, я надеюсь, что у вас есть), но я решил добавить свое решение для других с тем же вопросом.

Я также удалил if ($this->state() === self::STATE_TDIRTY), поскольку preInsert() применяется только для записей TDIRTY

0 голосов
/ 13 января 2011

replace() может работать, если вы включите идентификатор строки.

0 голосов
/ 20 декабря 2010

Я думаю, что ответ Владимира правильный, вам просто нужно добавить логику обновления перед skipOperation.

public function preSave($event)
{
    if (!$this->isUniqueEmail()) {
        // update logic

        $event->skipOperation();
    }
}

Извините, но я не могу комментировать ответ Владимира.

0 голосов
/ 31 марта 2010
    public function preSave($event)
    {
        if (!$this->isUniqueEmail()) {
            $event->skipOperation();
        }
    }

Но я предлагаю вам использовать валидаторы для этого.

...