Doctrine Entity increase value (Download counter)

You can also do the following in an entity repository:

return $this
    ->createQueryBuilder('f')
    ->update($this->getEntityName(), 'f')
    ->set('f.downloadCounter', $file->getDownloadCounter() + 1)
    ->where('f.id = :id')->setParameter('id', $file->getId())
    ->getQuery()
    ->execute();

Or using DQL:

 $em = $this->getDoctrine()->getManager();
 $query = $em->createQuery(
     'UPDATE YourBundle:File f
      SET f.downloadCounter = :downloadCounter'
 )->setParameter('downloadCounter', $file->getDownloadCounter() + 1);

Or through a simplified DQL:

 $em = $this->getDoctrine()->getManager();
 $query = $em->createQuery(
     'UPDATE YourBundle:File f
      SET f.downloadCounter = f.downloadCounter + 1'
 );

The drawback with these solutions: if your entity was already loaded it will have the previous count and not the incremented count.

The way you did is perfectly fine but a better way is to add an increment method to your entity.

Follow-up from Radu C comment below: the simplified DQL is the only solution that guarantees proper count.

The query increments based on the value in the database and locks the table guaranteeing queries to be executed in a sequence.

Whereas the other queries use the value in PHP runtime which may be an outdated value: some other request may have already incremented the value in the database therefore incrementing based on value in PHP memory will override increment made by other requests.


Safest way to do this is using Doctrine DBAL and call raw SQL that way you remove the chance of race condition and make the change atomic. Other option is to make the field versioned and use optimistic locking or pessimistic DB-level locking.