我正在开发一个 Symfony 5 应用程序,其中实体
InventaireActif
和 TypeActif
具有多对多关系。通过 Symfony 表单管理这种关系时会出现问题。
在我的
TypeActif
表单中,当我添加 InventaireActif
实体时,除非我在表单生成器中设置 'by_reference' => false
选项,否则它们不会持久保存到数据库中。我想在不依赖此选项的情况下实现正确的行为。
InventaireActif.php:
/**
* @ORM\ManyToMany(targetEntity=TypeActif::class, inversedBy="lesActifs")
*/
private $lesTypesActifs;
public function __construct()
{
$this->lesTypesActifs = new ArrayCollection();
// ... other initializations ...
}
/**
* @return Collection<int, TypeActif>
*/
public function getLesTypesActifs(): Collection
{
return $this->lesTypesActifs;
}
public function addLesTypesActif(TypeActif $lesTypesActif): self
{
if (!$this->lesTypesActifs->contains($lesTypesActif)) {
$this->lesTypesActifs[] = $lesTypesActif;
}
return $this;
}
public function removeLesTypesActif(TypeActif $lesTypesActif): self
{
$this->lesTypesActifs->removeElement($lesTypesActif);
return $this;
}
TypeActif.php:
/**
* @ORM\ManyToMany(targetEntity=InventaireActif::class, mappedBy="lesTypesActifs")
*/
private $lesActifs;
public function __construct()
{
$this->lesActifs = new ArrayCollection();
// ... other initializations ...
}
public function getLesActifs(): Collection
{
return $this->lesActifs;
}
public function addLesActif(InventaireActif $lesActif): self
{
if (!$this->lesActifs->contains($lesActif)) {
$this->lesActifs[] = $lesActif;
$lesActif->addLesTypesActif($this);
}
return $this;
}
public function removeLesActif(InventaireActif $lesActif): self
{
if ($this->lesActifs->removeElement($lesActif)) {
$lesActif->removeLesTypesActif($this);
}
return $this;
}
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
// ... other fields ...
->add('lesActifs', EntityType::class, [
'required' => false,
'class' => InventaireActif::class,
'choice_label' => 'libelle',
// 'by_reference' => false,
'multiple' => true,
'query_builder' => function (InventaireActifRepository $repo) {
return $repo->lesActifsReformesSortedASC();
},
]);
}
public function new(Request $request, TypeActifRepository $typeActifRepository, EntityManagerInterface $entityManager): Response
{
$typeActif = new TypeActif();
$form = $this->createForm(TypeActifType::class, $typeActif);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$typeActifRepository->add($typeActif, true);
return $this->redirectToRoute('app_type_actif_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('type_actif/new.html.twig', [
'type_actif' => $typeActif,
'form' => $form,
]);
}
当
'by_reference' => false
取消注释时,表单工作正常,并且 ManyToMany 关系按预期更新。
但是,我想避免使用
'by_reference' => false
。如果没有此选项,通过 InventaireActif
表单添加 TypeActif
实体不会保留更改。
确保两个实体中的
add
和 remove
方法同步。
审查了 Dotrine 配置和注释。
通过
InventaireActif
表单添加 TypeActif
实体时,应将更改保存到数据库,而不需要设置 'by_reference' => false
。
如果没有
'by_reference' => false
,更改不会持久。没有显示错误,日志也没有显示任何异常。
如果
by_reference
设置为 true
(或被省略),Symfony 的表单系统只是使用 ArrayCollection
类的方法将选定的实体添加到指定的属性。如果 by_reference
设置为 false
,它将使用您指定的自定义添加/删除方法。
将实体保存到数据库时,仅保存对多对多关系的owning侧所做的更改。代码中的拥有方是
$lesTypesActifs
类中的 InventaireActif
属性。
在您的表单中,如果没有
by_reference = false
,您仅更新 $lesActifs
实体的 TypeActif
属性,这是关系的 inverse 方面,因此这就是不保存更改的原因。但如果您添加 by_reference = false
,自定义添加/删除方法可确保拥有方也已更新,因此更改将被保存。
我不确定您是否还有一个通过修改
InventaireActif
属性来更新 $lesTypeActif
实体的表单,但如果没有,您可能只需切换实体的拥有和反面即可摆脱by_reference = false
:
class TypeActif {
/**
* @ORM\ManyToMany(targetEntity=InventaireActif::class, inversedBy="lesTypesActifs")
*/
private $lesActifs;
public function __construct()
{
$this->lesActifs = new ArrayCollection();
// ... other initializations ...
}
public function getLesActifs(): Collection
{
return $this->lesActifs;
}
}
class InventaireActif {
/**
* @ORM\ManyToMany(targetEntity=TypeActif::class, mappedBy="lesActifs")
*/
private $lesTypesActifs;
public function __construct()
{
$this->lesTypesActifs = new ArrayCollection();
// ... other initializations ...
}
/**
* @return Collection<int, TypeActif>
*/
public function getLesTypesActifs(): Collection
{
return $this->lesTypesActifs;
}
}