doktrin benzersiz bir alanda dayalı bir yöntem güncelleştirme / ekleme kaydetmek

6 Cevap php

O kadar çok yazı okudum ve ben güncelleme vs eklemek için kaydetmek için nasıl hakkında birçok varyasyonu bulundu ama benim için çalışacak bir şey bulamadı.

Ben preSave preSave save () () varsa tarafından otomatik olarak yürütülmektedir gitmek için yol olacağını tahmin ediyorum.

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

I need save() to check if a filed is set to be unique if so, to check if field data in this case email address is unique. Based on that info decide to insert or update posted fields that have changed.

6 Cevap

Sadece biraz daha mantık ekleyerek, orada bunu yapmanın daha iyi yolları olabilir, ama bu benim için çalışıyor olabilir.

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();
        }
    }
}
    public function preSave($event)
    {
        if (!$this->isUniqueEmail()) {
            $event->skipOperation();
        }
    }

Ama bunun için doğrulayıcılar kullanmanızı öneririm.

Ben sadece skipOperation önce güncelleme mantığı eklemek gerekir, Vladimir'in cevap hakkını sanırım.

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

        $event->skipOperation();
    }
}

Üzgünüm, ama Vladimir'in cevap üzerine yorum yapamam.

Ben sadece benzer bir durum içine çalıştırdıktan sonra bu soruyu kazılıp ettik. @ Peter cevabı ben aradığım hemen hemen ne olduğunu, ama ben birkaç değişiklik ekledik.

/**
 * 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() yerine refresh() kullanılarak sen 1 daha az SELECT sorgusu gerçekleştirmek anlamına gelir.

Ben bu sorun (en azından ben var umarım) bir cevap olması muhtemeldir biliyorum, ama ben aynı soru ile başkaları için benim çözüm eklemek düşündüm.

Ben de preInsert() sadece TDIRTY kayıtlar için geçerlidir if ($this->state() === self::STATE_TDIRTY) olarak kaldırdık

I know I'm a bit late here, but I found this post on Google while I was trying to update a field in a preInsert hook. I couldn't do that following what you've done, since your goal is only to refresh the Doctrine-Record, not to update it in DB (from what I understand ^^)

DB bir güncelleştirme gerçekleştirmek için, ben (ben yine "kurtarmak" aramak zorunda şaşırdı) lollowing kodu kullanmak zorunda

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