我想在我的学说实体中增加一个值。
目前我是这样做的。
$file->setDownloadCounter($file->getDownloadCounter() + 1);
$em = $this->getDoctrine()->getManager();
$em->persist($fileVersion);
$em->flush();
是否有办法执行这样的学说:
UPDATE file SET downloadCounter = downloadCounter + 1 WHERE id = 1
编辑:上面的原则示例中的问题是,在加载和刷新之间是其他人可以下载文件的时间,因此计数器不正确。
您还可以在实体存储库中执行以下操作:
return $this
->createQueryBuilder('f')
->update($this->getEntityName(), 'f')
->set('f.downloadCounter', $file->getDownloadCounter() + 1)
->where('f.id = :id')->setParameter('id', $file->getId())
->getQuery()
->execute();
或使用DQL:
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
'UPDATE YourBundle:File f
SET f.downloadCounter = :downloadCounter'
)->setParameter('downloadCounter', $file->getDownloadCounter() + 1);
或者通过简化的DQL:
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
'UPDATE YourBundle:File f
SET f.downloadCounter = f.downloadCounter + 1'
);
这些解决方案的缺点是:如果您的实体已经加载,它将具有先前的计数,而不是增量计数。
你这样做是完美的,但一个更好的方法是添加一个增量方法到你的实体。
Radu C的后续评论如下:简化的DQL是保证正确计数的唯一解决方案。
查询根据数据库中的值递增,并锁定表,保证查询按顺序执行。
而其他查询在PHP运行时使用的值可能是一个过时的值:一些其他请求可能已经在数据库中增加了值,因此基于PHP内存中的值增加将覆盖其他请求的增量。
最安全的方法是使用Doctrine DBAL并调用原始SQL,这样可以消除竞争条件的可能性并使更改原子化。另一种选择是对字段进行版本控制,并使用乐观锁定或悲观的db级锁定。
您可以简单地在您的模型中添加一个增量方法。
class File {
public function increaseDownloadCounter()
{
$this->downloadCounter++;
}
}
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('AcmeDemoBundle:EntityName')->find($entityId);
$valueToIncrement = $entity->getMyField(); // where MyField is the DB field to increment
$entity->setMyField(++$valueToIncrement);
$em->persist($entity);
$em->flush();