在插入Doctrine之前,检查数据库中是否已存在实体

时间:2010-05-08 15:47:38

标签: doctrine unique-constraint

每当我插入数据库中已存在的实体时,我都会收到错误,因为其中一个字段(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();
    }

有更简单的方法吗?

3 个答案:

答案 0 :(得分: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 :(得分:1)

在构建数据库支持的记录器时,我遇到了类似的问题。为防止警告疲劳,我为每条日志消息分配一个UID,这是其标识内容的散列,并使UID成为唯一密钥。

当然,这要求我确定是否已存在与该UID值匹配的记录(在我的情况下,我为该日志记录增加count值并触及其updated_at时间戳。 / p>

我最终在我的模型类中覆盖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()可能是更好的方法。在我的情况下,我不得不等到执行预保存挂钩(使用Doctrine template that I had created设置UID),所以我不得不改写save()

答案 2 :(得分:-7)

您应该使用Memcached或Redis队列来检查项目是否存在。