symfony - Symfony + Forms,by_reference = true 和 CollectionType 字段中的 allow_add
问题描述
我对 Symfony 比较陌生,所以我可能会严重误解一些东西。我对何时想by_reference = true
在 CollectionType 表单字段上设置allow_add = true
.
preRemove
对于上下文:当我尝试使用学说事件侦听器来侦听通过从 CollectionType 表单字段中删除实体allow_delete => true
以触发父实体的更新时,我陷入了困境。在by_reference => false
表单类中,我无法访问 preRemove 处理程序中的父实体,但调用了父实体的 removeEntity() 方法。使用by_reference => true
,我可以从要删除的实体访问父级,但它的 removeEntity() 方法不会被调用。这对我来说很有意义,我的麻烦在于添加带有表单的子实体。
简化,我有两个实体:
// SimpleParent.php
/**
* @ORM\Entity(repositoryClass="App\Repository\SimpleParentRepository")
*/
class SimpleParent
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\OneToMany(targetEntity="App\Entity\ChildEntity", mappedBy="parent", orphanRemoval=true, cascade={"persist", "remove"})
*/
private $childEntities;
public function addChildEntity(ChildEntity $childEntity): self
{
if (!$this->childEntities->contains($childEntity)) {
$this->childEntities[] = $childEntity;
$childEntity->setParent($this);
}
return $this;
}
// other getter, adder, remover methods as autogenerated, left out for brevity
}
和
// ChildEntity.php
/**
* @ORM\Entity(repositoryClass="App\Repository\ChildEntityRepository")
*/
class ChildEntity
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\SimpleParent", inversedBy="childEntities")
* @ORM\JoinColumn(nullable=false)
*/
private $parent;
// getter, adder, remover methods as autogenerated, left out for brevity
}
有两个非常简单的表单类:
class SimpleParentType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => SimpleParent::class,
]);
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('childEntities', NiceRepeaterType::class, [
"entry_type" => ChildEntityType::class,
"allow_delete" => true,
"by_reference" => true,
"allow_add" => true,
]);
}
}
class ChildEntityType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => ChildEntity::class,
]);
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add("name", TextType::class, ["required" => false]);
}
}
和控制器中的一个非常简单的代码(为简单起见,我只是在这里刷新 entityManager)
$form = $this->createForm(SimpleParentType::class, $simpleParent);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$simpleParent = $form->getData();
$this->entityManager->flush();
}
类是use
正确的,为简洁起见。使用原型,我添加了一个新行。但是,提交表单会引发异常:
An exception occurred while executing 'INSERT INTO child_entity (name, parent_id) VALUES (?, ?)' with params ["aaa", null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'parent_id' cannot be null
如果我将 ChildEntity 上的连接列设为可为空,则会插入 ChildEntity 但与 SimpleParent 没有连接,因为 parent_id 设置为 null。不用说,这些插入的 ChildEntity 行不会显示在 Collection 的表单中。这是有道理的,因为父级的加法器永远不会被调用,因此它永远不会setParent($this)
在新的 ChildEntity 上调用。
使用by_reference => false
,它可以按预期完美运行,创建 ChildEntity 并将其传递给设置 ChildEntity 父级的 SimpleParent::addChildEntity。刷新实体管理器时,将插入 ChildEntity 行,并将 parent_id 设置为 SimpleParent 的 id。
我的问题是:by_reference => true
如果我也想要,为什么我还要使用 CollectionType allow_add => true
?我注意到我从$form->getData()
控制器中获取的对象包含 Collection,包括当前没有父级的 ChildEntity。我可以手动做到这一点
$simpleParent = $form->getData();
foreach($simpleParent->getChildEntities() as $child) {
$child->setParent($simpleParent);
}
但是这种方法有什么原因呢?我觉得我错过了一些明显的东西。任何建议表示赞赏。
解决方案
推荐阅读
- amazon-web-services - 如何限制 AWS 自动缩放以不允许使用特定角色?
- laravel - (VueJS, Axios) 捕获错误的不同方法
- java - 单调法
- javascript - 文件系统访问 API createWritable() 方法在控制台中有效,但在脚本中无效
- mysql - 如何从具有旋转 IP 地址的 EC2 实例访问 Amazon RDS 上的 MySQL?
- bash - 如何从bash脚本中去除简单的引号
- c++ - 重复模板参数的快捷方式
- c# - 从 where 子句中删除列我可以使用吗?操作员
- r - R中未熔化表的问题
- arrays - 从用户搜索传递值数组时,Mongodb $in 因添加引号而失败