Check if entity exists in database before inserting with Doctrine

Whenever I insert an entity that already exists in the database, I get an error because there is one single constraint on one of the fields ( email

).

So, I want to check if it exists; if not, I paste it.

My code looks like this:

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

      

Is there an easier way to do this?

+2


a source to share


3 answers


Place the code you have in your UserTable class like 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;
}

      



Now you can call the method, and the returned object will be the existing record (if any) or the one you just created.

+8


a source


I had to face a similar issue when creating a database backed database. To prevent warning fatigue, I assign each log message a UID that is a hash of its identifying content and make the UID a unique key.

Naturally, this requires determining if an existing entry exists that matches this UID value (in my case, I increment the value count

for this log entry and touch its flag updated_at

).

I ended up redefining Doctrine_Record::save()

in my model class, similar to this (code adjusted to be more relevant to your situation):

  /** 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()

as follows:

  /** Locates an existing record that matches the specified user 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();
  }

      

Note that this is probably the best approach for rewriting preSave()

, not save()

in your model. In my case, I had to wait for the pre-save quotes to complete (the UID was set using the Doctrine template I created ), so I had to overwrite instead save()

.

+1


a source


You have to use a Memcached or Redis queue to check if the item exists.

-7


a source







All Articles