Symfony 2 - 无法使用集合保存表单

Posted

技术标签:

【中文标题】Symfony 2 - 无法使用集合保存表单【英文标题】:Symfony 2 - can't save form with collections 【发布时间】:2015-09-30 13:27:44 【问题描述】:

我正在为一些 symfony 2 表单问题苦苦挣扎。尝试保存我的表单时,我收到以下消息:

通过关系发现了一个新实体 'Org\CoreBundle\Entity\CustomLists#customListElements' 不是 配置为实体级联持久化操作: 组织\CoreBundle\Entity\CustomListElement@000000007db26fee000000007e19f46a。 要解决这个问题:要么显式调用 EntityManager#persist() 这个未知实体或配置级联将这个关联保持在 例如@ManyToOne(..,cascade="persist") 的映射。

我已经在集合元素上调用了 persist() 方法,并在我的实体中添加了 cascade="persist",这是在类似线程中推荐的,但没有帮助。

CustomLists.php

 /**
     * @var \Doctrine\Common\Collections\Collection
     * @ORM\OneToMany(targetEntity="CustomListElement", mappedBy="customList", cascade="persist")
     */
    private $customListElements;

/**
     * Add customListElement
     *
     * @param \Org\CoreBundle\Entity\CustomListElement $customListElement
     *
     * @return CustomLists
     */
    public function addCustomListElement(\Org\CoreBundle\Entity\CustomListElement $customListElement)
    
        $this->customListElements[] = $customListElement;

        return $this;
    

    /**
     * Remove customListElement
     *
     * @param \Org\CoreBundle\Entity\CustomListElement $customListElement
     */
    public function removeCustomListElement(\Org\CoreBundle\Entity\CustomListElement $customListElement)
    
        $this->customListElements->removeElement($customListElement);
    

CustomListElement.php:

 /**
     * 
     * @ORM\ManyToOne(targetEntity="CustomLists", inversedBy="customListElements", cascade="persist")
     * @ORM\JoinColumn(name="custom_list", referencedColumnName="id_custom_list", nullable=false)
     */
    private $customList;

  /**
     * Set customList
     *
     * @param \Org\CoreBundle\Entity\CustomLists $customList
     * 
     * @return CustomListElement
     */

    public function setCustomList(\Org\CoreBundle\Entity\CustomLists $customList = null)
    
        $this->customList = $customList;

        return $this;
    

CustomListType.php:

    $builder->add('customListElements', 'collection', array(
            'type' => new CustomListElementType(),
            'label' => false,
            'allow_add' => true,
            'allow_delete' => true,
            'prototype' => true,
            'attr' => array('class' => 'form-control')
    ));

控制器:

   if ($form->isValid()) 
        $data = $form->getData();

        $customListElements = $data->getCustomListElements();
         foreach($customListElements as $element)
            $element->setCustomList($data);
            $em->persist($element);
            $em->flush();
               

        $em->persist($data);
        $em->flush();
    

我真的不知道,我做错了什么。我会非常感谢任何有用的答案。

编辑: 这是我的表单代码:

% extends 'OrganizerBundle::layout.html.twig' %

% block title % title % endblock %

% block header %
 parent() 
% endblock %

% block content %
    <div class="col col-md-8">
        <div class="panel panel-success custom-list-form">
          <div class="panel-heading">
            <h3 class="panel-title"> title </h3>
          </div>
          <div class="panel-body">
             form_start(form) 

                 form_row(form.listName) 

                <h3>Elementy</h3>

                <ul class="elements" 
                data-prototype="% filter escape %% include 'OrganizerBundle:CustomLists:elementTemplate.html.twig'  %% endfilter %">
                % for tag in form.customListElements %
                    <li>
                    <div class="custom-list-element">
                        <div id="customList_customListElements___name__">
                            <div>
                                  form_row(tag.elementName) 
                            </div>
                            <div>
                                 form_row(tag.elementDescription) 
                            </div>
                            <input type="hidden" id="customList_customListElements___name___elementOrder"
                                name="customList[customListElements][__name__][elementOrder]" />
                        </div>
                        <div class="element-buttons">
                            <i class="fa fa-times remove-element" title=" 'Usuń'|trans " data-placement="left" data-toggle="tooltip"></i>
                        </div>

                        </div>
                    </li>
                % endfor %

                </ul>
                % do form.customListElements.setRendered %
                <div class="form-buttons"> form_widget(form.zapisz) </div>
             form_end(form) 
          </div>
        </div>
    </div>
    <script>
    var $collectionHolder;

    var addElemText = ' 'Dodaj element'|trans ';
    var $newElementButton = $('<a href="#" class="add_element_link"><button type="button" class="btn btn-primary btn-sm">'+ 
            addElemText +'</button></a>');
    var $newLinkLi = $('<li></li>');

    jQuery(document).ready(function() 

        $collectionHolder = $('.elements');

        $newElementButton.insertBefore($collectionHolder);
        $collectionHolder.data('index', $collectionHolder.find(':input').length);

        $newElementButton.on('click', function(e) 
            e.preventDefault();
            addElementForm($collectionHolder, $newLinkLi);
        );

        function addElementForm($collectionHolder, $newLinkLi) 

            var prototype = $collectionHolder.data('prototype');
            var index = $collectionHolder.data('index');
            var newForm = prototype.replace(/__name__/g, index);

            $collectionHolder.data('index', index + 1);

            var $newFormLi = $('<li></li>').append(newForm);
            $collectionHolder.append($newFormLi);
        

    );
    </script>
% endblock %

还有我的 elementTemplate.html.twig 原型模板:

<div class="listBox" data-pk=" element.idCustomList ">
    <input type="checkbox" class="list-checkbox"/>
    <div class="custom-list-name"> element.listName </div>
    <div class="list-elem-count"> 'elementów:'|trans ~ '...' </div>
    <div class="list-elem-created">
        <span class="created-text"> 'utworzono:'|trans </span>
        <div class="date-created"> '...'  </div>
    </div>
</div>

编辑 2: 我在doctrine:schema:validate做的时候,也报错:

[映射] FAIL - 实体类 'Org\CoreBundle\Entity\CustomLists' 映射无效: * 字段 Org\CoreBundle\Entity\CustomLists#customListElements 位于双向关系的反面,但指定 目标实体上的 mappedBy 关联 Org\CoreBundle\Entity\CustomListElement#customList 不包含 所需的 'inversedBy="customListElements"' 属性。

【问题讨论】:

如果您使用的是mappedBy,则需要指定inversedBy。这可以解释这个问题。并尝试在您的addCustomListElement() 中添加$customListElement-&gt;setCustomList($this),即使没有必要,这也是一种很好的做法。 此外,每个请求几乎不需要超过一个 flush()。如果您在持久化/刷新新的 CustomList 之前刷新 CustomListElements,那么 Doctrine 将没有 CustomList ID 可以放在 CustomListElements 表中。 【参考方案1】:

你是否在 CustomLists.php 的构造函数中添加了这一行:

$customListElements = new ArrayCollection();

在 OneToMany 声明中将级联更改为全部。

/**
     * @var \Doctrine\Common\Collections\Collection
     * @ORM\OneToMany(targetEntity="CustomListElement", mappedBy="customList", cascade="all")
     */
    private $customListElements;

不必读取所有 $customListElements 并手动添加。 Doctrine 会自动执行此操作,因为他知道由于 OneToMany,CustomLists 与 CustomListElement 有关系。

你可以这样改变你的控制器:

$entity = new CustomLists();
$form = $this->createForm(new CustomListType(), $entity);
$form->handleRequest($request); 

if ($form->isValid()) 
       $em->persist($entity);
       $em->flush();    

希望有帮助

【讨论】:

不幸的是,在做了以上所有操作后,它仍然出现 尝试在您的addCustomListElement() 方法中使用$this-&gt;customListElements-&gt;add($customListElement); 您是否使用 javascript 代码在模板中显示您的收藏? @Ryan - 还是一样。我正在使用 javascript 和我自己的原型模板来添加新元素。 @Tungenius - 是的,我已经编辑了我的帖子并在那里放置了一个代码

以上是关于Symfony 2 - 无法使用集合保存表单的主要内容,如果未能解决你的问题,请参考以下文章

Adobe Reader来填写的表单无法保存,我怎么做pdf表单才能使别人可以用Adobe Reader来填写的表单能保存

无法使用 Symfony2 和 TinyMCE 提交表单

Symfony 2 中的 ArrayCollection(表单集合)索引冲突

Symfony 5 表单通知:App\Entity\Epic 类的对象无法转换为 int

Symfony 渲染一个集合表单类型原型

枚举和 Symfony 表单的教义集合