2010-05-08 41 views
2

插入每當我插入已經存在於數據庫中的實體之前存在,我得到一個錯誤,因爲沒有對領域之一(email)的唯一約束。檢查實體已經在數據庫主義

所以,我要檢查它是否已經存在;如果沒有,我插入它。

我的代碼如下所示:

$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

把你的代碼到一個方法在用戶表類如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成爲唯一密鑰。

當然,這要求我確定一個記錄是否已經存在與該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的隊列,以檢查項目存在與否。

相關問題