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

Doctrine 在插入之前,请检查数据库中是否已存在实体,doctrine,unique-constraint,Doctrine,Unique Constraint,每当我插入数据库中已经存在的实体时,我都会收到一个错误,因为其中一个字段(email)上存在唯一约束 所以我想检查它是否已经存在;如果没有,我将其插入 我的代码如下所示: $q = Doctrine_Query::create() ->from('User u') ->where('u.email = ?', $email); $object = $q->fetchOne(); if( ! is_object($object)) { $u

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

有更简单的方法吗?

将您的代码放入UserTable类中的方法中,例如
insertIfNotExists()


现在您可以调用该方法,返回的对象将是现有记录(如果有)或您刚刚创建的记录。

将您拥有的代码放入UserTable类中的方法中,例如
insertIfNotExists()


现在您可以调用该方法,返回的对象将是现有记录(如果有)或您刚刚创建的记录。

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

当然,这需要我确定是否已经存在与该UID值匹配的记录(在我的例子中,我为该日志记录增加一个
count
值,并在时间戳处触摸其
updated_)

我最终在我的模型类中重写了
Doctrine\u Record::save()
,与此类似(代码调整为与您的情况更相关):

UserTable::findDuplicate()
如下所示:

$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();
    }
  /** 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是使用a设置的),所以我不得不覆盖
save()

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

当然,这需要我确定是否已经存在与该UID值匹配的记录(在我的例子中,我为该日志记录增加一个
count
值,并在
时间戳处触摸其
updated_)

我最终在我的模型类中重写了
Doctrine\u Record::save()
,与此类似(代码调整为与您的情况更相关):

UserTable::findDuplicate()
如下所示:

$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();
    }
  /** 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是使用a设置的),所以我必须覆盖
save()
相反。

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

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

请在您的答案中添加一些解释,以便其他人可以从中学习-为什么这是一个好主意?如果另一个进程将数据添加到数据库中,而不是缓存层,该怎么办?要进行简单的“查找”,最好使用诸如memcached或Redis之类的缓存引擎,因为它更快、更具可扩展性。请对您的答案添加一些解释,以便其他人可以从中学习-为什么这是一个好主意?如果另一个进程向数据库中添加数据,而不是向缓存层中添加数据,该怎么办?要进行简单的“查找”,最好使用诸如memcached或Redis之类的缓存引擎,因为它更快、更具可扩展性。