2010-05-08 9 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(); 
    } 

이 작업을 수행하는 쉬운 방법이 있나요?

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

지금 당신이 메소드를 호출 할 수 있으며, 반환되는 객체는 기존 기록 될 것입니다 (있는 경우), 또는 :

답변

8

당신의 USERTABLE 클래스 예를 들어 insertIfNotExists()의 방법으로 당신이 가지고있는 코드를 넣어 방금 만든 방.

1

데이터베이스 백업 로거를 구축하는 동안 비슷한 문제가 발생했습니다. 경고 피로를 막기 위해 각 로그 메시지에 식별 내용의 해시 인 UID를 할당하고 UID를 고유 키로 지정했습니다.

당연히이 경우 해당 UID 값과 일치하는 레코드가 이미 존재하는지 확인해야합니다 (필자의 경우 해당 로그 레코드에 대해 count 값을 증가시키고 해당 updated_at 타임 스탬프를 터치합니다).

/** 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()

는 다음과 같습니다 :

나는 (코드는 상황에 더 관련 조정)이 유사하게, 내 모델 클래스에 Doctrine_Record::save()를 오버라이드 (override) 결국

/** 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(); 
    } 

참고 모델에서 save()이 아닌 preSave()을 덮어 쓰면 더 나은 방법 일 수 있습니다. 필자의 경우, 사전 저장 후크 (Doctrine template that I had created을 사용하여 UID가 설정 됨)가 실행될 때까지 기다려야하므로 대신 save()을 덮어 써야했습니다.

-7

항목이 있는지 여부를 확인하려면 Memcached 또는 Redis 대기열을 사용해야합니다.

관련 문제