2

データベースに既に存在するエンティティを挿入するたびに、フィールドの 1 つに一意の制約があるため、エラーが発生します ( 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 に答える