I want to increase a value in my doctrine entity.
Currently I'm doing it this way.
$file->setDownloadCounter($file->getDownloadCounter() + 1);
$em = $this->getDoctrine()->getManager();
$em->persist($fileVersion);
$em->flush();
Is there way to execute something like this in doctrine:
UPDATE file SET downloadCounter = downloadCounter + 1 WHERE id = 1
EDIT:
The problem in the doctrine example above is that between loading and flush is time where others could download the file and so the counter is not correct.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With