Symfony3 CollectionType,Data返回null

时间:2016-07-15 07:42:21

标签: php symfony

使用symfony创建collectiontype没什么问题..

我尝试过多个教程,比如 http://symfony.com/doc/current/cookbook/form/form_collections.htmlhttp://toni.uebernickel.info/2012/03/15/an-example-of-symfony2-collectiontype-form-field-prototype.html ..

但总是有相同的结果。

$tags = $form->get('tags')->getData();返回null。

我能够生成添加/删除链接,索引也在工作,但是将数据导入控制器......

我错过了重要的事情或做错了什么吗?希望有人可以帮助我或给小费。

我现在有什么

任务实体

 /**  
 * @ORM\OneToMany(targetEntity="Tag", mappedBy="task",
 cascade={"persist", "remove"})  
 * /  protected $tags;

标记实体

 /**  
 * @ORM\ManyToOne(targetEntity="Task", inversedBy="tags")  
 * @ORM\JoinColumn(name="tag_id", referencedColumnName="id")  
 * / 
 protected $task;

任务类型

->add('tags', CollectionType::class, array(
'entry_type' => TagType::class,
'allow_add' => true,
'allow_delete' => true,
'prototype_name' => '__tag__name__',))

TagType

$builder->add('name', TextType::class, array()));

{% macro widget_prototype(widget, remove_text) %}
   {% if widget.vars.prototype is defined %}
      {% set form = widget.vars.prototype %}
      {% set name = widget.vars.prototype.vars.name %}
   {% else %}
      {% set form = widget %}
      {% set name = widget.vars.full_name %}
   {% endif %}

   <div data-content="{{ name }}">
      <a class="btn-remove" data-related="{{ name }}">{{ remove_text }}</a>
       {{ form_widget(form) }}
   </div>

{% endmacro %}

枝条

<div id="post_tags" data-prototype="{{ _self.widget_prototype(form.tags, 'Remove tag')|escape }}">
 {% for widget in form.tags.children %}
     {{ _self.widget_prototype(widget, 'Remove tag') }}
 {% endfor %}
</div>
<a class="btn-add" data-target="post_tags">Add tag</a>

JS

jQuery(function($) {
    $(document).on('click', '.btn-add[data-target]', function(event) {
        var collectionHolder = $('#' + $(this).attr('data-target'));

        if (!collectionHolder.attr('data-counter')) {
            collectionHolder.attr('data-counter', collectionHolder.children().length);
        }

        var prototype = collectionHolder.attr('data-prototype');
        var form = prototype.replace(/__tag__name__/g, collectionHolder.attr('data-counter'));

        collectionHolder.attr('data-counter', Number(collectionHolder.attr('data-counter')) + 1);
        collectionHolder.append(form);

        event && event.preventDefault();
    });

    $(document).on('click', '.btn-remove[data-related]', function(event) {
        var name = $(this).attr('data-related');
        $('*[data-content="'+name+'"]').remove();

        event && event.preventDefault();
    });
});

并在控制器

$form = $this->createForm(TaskType::class, $task);

编辑/更新

任务实体设置者和标签的获取者

public function __construct()
{
   $this->tags = new \Doctrine\Common\Collections\ArrayCollection();
}

public function add(Tag $tag)
{
   $this->tags[] = $tag;
   return $this;
}

public function removeTag(Tag $tag)
{
   $this->tags->removeElement($tag);
}

public function getTags()
{
   return $this->tags;
}

控制器:

$task = new Task();
$form = $this->createForm(TaskType::class, $task);
$form->handleRequest($request);
if($form->isValid()){
    $tags = $form->get('tags')->getData();

     foreach($tags as $tag){
         //Here var_dump, echo, print, array_push etc tricks = empty
     }

     //Also without foreach var_dump = empty
}

1 个答案:

答案 0 :(得分:1)

感谢您更新您的问题并提供更多详情。

要立即解决您的问题,请记住,Doctrine级联仅检查拥有方(已反转的一方 - 在这种情况下需要保持原样)。所以你应该手动设置标签应该具有的任务。

public function add(Tag $tag)
{
   $this->tags[] = $tag;
   $tag->task = $this;//added this line
   return $this;
}

假设 - 我相信你没有检查过你真正需要的东西。对于正确的解决方案,我假设您需要此功能,一个任务有多个标签,标签可以在多个任务中重复使用。

在这种情况下:

<强> 1。你正在使用OneToMany关系。如果你看一下你所引用的第一个教程,你需要ManyToMany http://symfony.com/doc/current/cookbook/form/form_collections.html

<强> 2。此外,您需要一个单向的ManyToMany。为什么?您在任务中分配标签,而不是相反。另外,也许你需要标记其他实体。

有关ManyToMany(单向)的文档,请查看http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/association-mapping.html#many-to-many-unidirectional

任务实体

/**
 * @var ArrayCollection
 *
 * @Assert\Valid
 * @ORM\ManyToMany(targetEntity="Tag")
 * @ORM\JoinTable(name="tasks_tags",
 *  joinColumns={@ORM\JoinColumn(name="task_id", referencedColumnName="id", onDelete="CASCADE")},
 *  inverseJoinColumns={@ORM\JoinColumn(name="tag_id", referencedColumnName="id")}
 * )
 */
 protected $tasks;

标记实体

protected $ tasks;

注意:当您从任务中删除标记,并且没有其他任务使用您删除的标记时,该标记将保留为“孤儿”。 Doctrine与ManyToMany关系中的孤立删除不兼容,因此您必须手动删除这些孤立。或者您可以将标签放在周围,未使用,以便稍后添加。