我被困住了: - )
也许我的研究中只有错误的关键词。但我没有通过。所以我希望其中一个人可以帮助我!
我有一个单向的ManyToMany协会。当我尝试提交表单(因此持续存在)时,我收到错误:
通过“TrainerInnenPool \ AppBundle \ Entity \ Trainer #applicationFields”关系找到了一个新实体,该关系未配置为实体级联持久化操作:TrainerInnenPool \ AppBundle \ Entity \ ApplicationField @ 0000000022ef36c600000000087bcbc3。
当我执行“cascade persist”时,会创建一个实际已经存在的新实体。
我有2个实体:
Trainer具有与ApplicationField的单向ManyToMany关联:
class Trainer {
public function __construct()
{
$this->applicationFields = new ArrayCollection();
}
[...]
/**
* @ORM\ManyToMany(targetEntity="ApplicationField")
*/
protected $applicationFields;
ApplicationField具有自引用的OneToMany关联:
class ApplicationField {
public function __construct() {
$this->children = new ArrayCollection();
}
[...]
/**
* @ORM\OneToMany(targetEntity="ApplicationField", mappedBy="parent")
*/
private $children;
/**
* @ORM\ManyToOne(targetEntity="ApplicationField", inversedBy="children")
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
*/
private $parent;
我想创建一个表单,我可以在其中添加Trainer - ApplicationField关联。
因此我有一个ApplicationFieldCollectionType:
class ApplicationFieldCollectionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('applicationFields', 'collection', array(
'type' => new ApplicationFieldType(),
'allow_add' => true,
'label' => false
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TrainerInnenPool\AppBundle\Entity\Trainer',
));
}
embeded类型如下:
class ApplicationFieldType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('applicationFieldName', 'entity', array(
'class' => 'TrainerInnenPoolAppBundle:ApplicationField',
'label' => false,
'mapped' => false,
'property' => 'name',
'query_builder' => function(EntityRepository $repository) {
return $repository->createQueryBuilder('application_field')
->where('application_field.parent is NULL');
}
));
$builder->add('name', 'entity', array(
'class' => 'TrainerInnenPoolAppBundle:ApplicationField',
'label' => false,
'property' => 'name',
'query_builder' => function(EntityRepository $repository) {
return $repository->createQueryBuilder('application_field')
->where('application_field.parent = 1');
}
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TrainerInnenPool\AppBundle\Entity\ApplicationField',
));
}
最后遗漏的部分:控制器:
public function editApplicationField($id, Request $request)
{
$entityManager = $this->getDoctrine()->getEntityManager();
$trainer = $entityManager->getRepository('TrainerInnenPoolAppBundle:Trainer')->find($id);
$editForm = $this->createForm(new ApplicationFieldCollectionType(), $trainer);
if ($request->getMethod() == 'POST') {
$editForm->handleRequest($request);
$entityManager->flush();
}
当我从Trainer中获取ApplicationField实体并尝试保留它们时,
$editForm->handleRequest($request);
$af = $trainer->getApplicationFields();
foreach ($af as $applicationField) {
$trainer->addApplicationField($applicationField);
$entityManager->persist($applicationField);
}
$entityManager->flush();
我无法这样做,因为我得到了“关键主要重复条目” - 例外。
我想我非常想念任何明显的观点。如果有人可以帮助我,给我一个提示或刚提到用信息更新我的问题,我会非常感激。
亲切的问候......
答案 0 :(得分:1)
由于缺少属性,因此未调用嵌套类型设置器:
->add('applicationFields', 'collection', array(
'type' => new ApplicationFieldType(),
...
'by_reference' => false
...
http://symfony.com/doc/current/reference/forms/types/collection.html#by-reference
当您计划拥有可添加/删除的收集字段时(" allow_add"," allow_delete"),您应始终提供" by_reference" => false选项,以便直接在相关实体上调用setter,然后构建关联,而不是从原始实体链接方法。
希望这有帮助!
答案 1 :(得分:0)
您需要cascade = {“persist”}注释,因为您希望将整个实体与ApplicationField的关联持久化。如果您不使用cascade = {“persist”},则必须手动保留实体。
实体已添加到培训师,因此如果您想手动保留实体,则应删除该行
$trainer->addApplicationField($applicationField);
并且只执行持久性。
这应该有效。试试吧。但我认为效果与使用级联持久性相同。所以这不是我认为的最终解决方案,而是理解问题的第一步,为什么手册持续存在以前不起作用。