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

有没有更简单的方法来做到这一点?

4

3 回答 3

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

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

于 2010-05-10T08:18:58.187 回答
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 模板设置的),所以我不得不改写save()

于 2012-03-04T22:11:56.037 回答
-9

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

于 2012-08-08T09:43:38.230 回答