我不喜欢使用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
。
任何帮助?
答案 0 :(得分:0)
好的,感谢@Cerad在我的问题评论中提出了建议。我确实需要detach and merge功能。因此,实体具有withBar(Bar $bar)
方法:
<?php
namespace App\Entity
use Doctrine\ORM\Mapping as ORM;
/**
* Foo
*
* @ORM\Table(name="foo", ...)
* @ORM\Entity
*/
class Foo
{
/**
* @var string
*
* @ORM\Column(name="id", type="string", length=36, nullable=false)
* @ORM\Id
*/
private $id;
/**
* @var Bar
*
* @ORM\Column(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 App\Repository;
use App\Entity\Foo;
use Doctrine\ORM\EntityManagerInterface;
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;
}
}
故意省略错误处理,因为这些例子无论如何都是设计的
感谢您的指针。如果你把它写成答案,我会高兴地接受它并给你代表