如何使用Doctrine2将实体的克隆保存为更新
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用Doctrine2将实体的克隆保存为更新相关的知识,希望对你有一定的参考价值。
我不喜欢使用setter,因为我不喜欢在实例化后改变对象,所以我倾向于使用返回克隆的withFoo(Foo $foo)
样式,而不是:
public function withFoo(Foo $foo): self
{
$clone = clone $this;
$clone->foo = $foo;
return $clone;
}
很长一段时间,这对我很有帮助,但现在我必须使用Doctrine2,它不起作用:
$foo = $fooRepository->getByBar($bar);
$foo = $foo->withBaz($baz);
$emi->flush();
这会导致我的日志出错,如下所示:
app.ERROR: An exception occurred while executing 'INSERT INTO foo (id, bar, baz) VALUES (?, ?, ?)' with params ["51f74f6e-8e20-42ec-ba21-ac3ae62658ef", "Bar", "Baz"]: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '51f74f6e-8e20-42ec-ba21-ac3ae62658ef' for key 'PRIMARY' [] []
如果我将我的代码更改为以下代码,它将更新没有问题:
public function withFoo(Foo $foo): self
{
$this->foo = $foo;
return $this;
}
现在我不得不求助于使用普通的二传手,但我不喜欢它。有没有办法做到这一点?
我想告诉它保存更新,但要使用ID来确定要更新的记录。例如,mysql中的REPLACE INTO
排序。
有帮助吗?
答案
好的,感谢@Cerad在我的问题评论中提出了建议。我确实需要detach and merge功能。所以实体有withBar(Bar $bar)
方法:
<?php
namespace AppEntity
use DoctrineORMMapping as ORM;
/**
* Foo
*
* @ORMTable(name="foo", ...)
* @ORMEntity
*/
class Foo
{
/**
* @var string
*
* @ORMColumn(name="id", type="string", length=36, nullable=false)
* @ORMId
*/
private $id;
/**
* @var Bar
*
* @ORMColumn(name="bar", type="object" ...)
*/
private $bar;
public function __construct(string $id, Bar $bar)
{
$this->id = $id;
$this->bar = $bar;
}
public function withBar(Bar $bar): self
{
$clone = clone $this;
$clone->bar = $bar;
return $clone;
}
}
这与在没有使用Doctrine的项目中一样,通过返回原始的修改后的COPY,而不是改变它。很高兴。
接下来,FooRepository
更新方法变为这样:
<?php
namespace AppRepository;
use AppEntityFoo;
use DoctrineORMEntityManagerInterface;
class FooRepository
{
private $emi, $repository;
public function __construct(EntityManagerInterface $emi)
{
$this->emi = $emi;
$this->repository = $emi->getRepository(Foo::class);
}
public function updateBar(string $id, Bar $bar): Foo
{
// Get the `Foo` and update the `Bar`
$foo = $this->repository->findOneBy(['id'=>$id]);
$foo = $foo->withBar($bar);
// Detach and merge the entity
// You can do the detach before the `withBar()` but it makes no difference
// as the modified entity is actually an entirely new object, so Doctrine
// can't see it until it's merged anyway
$this->emi->detach($foo);
$this->emi->merge($foo);
$this->emi->flush();
return $foo;
}
}
故意省略错误处理,因为这些例子无论如何都是设计的
谢谢你的指针。如果你把它写成答案,我会高兴地接受它并给你代表
以上是关于如何使用Doctrine2将实体的克隆保存为更新的主要内容,如果未能解决你的问题,请参考以下文章