2010-05-08 2 views
2

Когда я вставляю сущность, которая уже существует в базе данных, я получаю сообщение об ошибке, потому что в одном из полей есть уникальное ограничение (email).Проверьте, существует ли сущность в базе данных перед вставкой с помощью Doctrine

Поэтому я хочу проверить, существует ли он; если нет, я вставляю его.

Мой код выглядит следующим образом:

$q = Doctrine_Query::create() 
    ->from('User u') 
    ->where('u.email = ?', $email); 

$object = $q->fetchOne(); 

if(! is_object($object)) { 
      $user = new User(); 
      $user-email = $email; 
      $user->save(); 
    } 

Есть ли более простой способ сделать это?

ответ

8

Поместите код, который вы имеете в метод в вашем UserTable класса, например insertIfNotExists():

public function insertIfNotExists(User $user) 
{ 
    // Check if it exists first 
    $q = self::create("u") 
    ->where("u.email = ?", $user->email) 
    ->execute(); 

    // Do we have any? 
    if ($q->count()) 
    { 
    // Yes, return the existing one 
    return $q->getFirst(); 
    } 

    // No, save and return the newly created one 
    $user->save(); 
    return $user; 
} 

Теперь вы можете вызвать метод, а возвращаемый объект будет существующая запись (если таковой имеется), или тот, который вы только что создали.

1

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

Естественно, для этого требуется определить, существует ли запись, которая соответствует этому значению UID (в моем случае я увеличиваю значение count для этой записи журнала и коснусь его отметки времени updated_at).

Я закончил тем, перекрывая Doctrine_Record::save() в моем классе модели, так же, как это (код корректируется, чтобы быть более отношение к вашей ситуации):

/** Persists the changes made to this object and its relations into the 
    * database. 
    * 
    * @param $conn Doctrine_Connection 
    * @return void 
    */ 
    public function save(Doctrine_Connection $conn = null) 
    { 
    /* Invoke pre-save hooks. */ 
    $this->invokeSaveHooks('pre', 'save'); 

    /* Check to see if a duplicate object already exists. */ 
    if($existing = $this->getTable()->findDuplicate($this)) 
    { 
     /* Handle duplicate. In this case, we will return without saving. */ 
     return; 
    } 

    parent::save($conn); 
    } 

UserTable::findDuplicate() выглядит следующим образом:

/** Locates an existing record that matches the specified user's email (but 
    * without matching its PK value, if applicable). 
    * 
    * @param $user User 
    * 
    * @return User|bool 
    */ 
    public function findDuplicate(User $user) 
    { 
    $q = 
     $this->createQuery('u') 
     ->andWhere('u.email = ?', $user->email) 
     ->limit(1); 

    if($user->exists()) 
    { 
     $q->andWhere('u.id != ?', $user->id); 
    } 

    return $q->fetchOne(); 
    } 

Обратите внимание, что это, вероятно, лучший подход к перезаписыванию preSave(), а не save() в вашей модели. В моем случае мне пришлось подождать, пока не будут выполнены предварительные сохранения (UID был установлен с использованием Doctrine template that I had created), поэтому мне пришлось перезаписать save().

-7

Вы должны использовать очередь Memcached или Redis, чтобы проверить, существует ли элемент.

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