2016-07-15 128 views
1

我没有什么问题用symfony创建collectiontype ..返回为空Symfony3 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); 

编辑/ UPDATE

任务实体getter和setter方法的标签

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 
} 
+0

请在任务实体中显示您的获取者和设置者(用于标记)。 – galeaspablo

+0

您可以发布整个控制器,或者至少是您试图获取标签数据的相关部分吗? – DonCallisto

+0

已更新的问题,getters和setter是使用php bin/console doctrine生成的:generate:entities - 命令 – Degu

回答

1

感谢您更新您的问题,并提供更多详细信息。

要立即解决您的问题,请记住,Doctrine级联只会检查拥有方(具有inversedBy的一方 - 在此情况下需要保留它的位置)。所以你应该手动设置一个标签应该有的任务。

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

假设 - 我相信,你有没有检查你的实际需要。为了正确的解决方案,我假设你需要这个功能,一个任务有多个标签,一个标签可以在多个任务中重复使用。

在这种情况下:

1.您使用的是一对多的关系。如果你看一下你提到的第一个教程,需要多对多http://symfony.com/doc/current/cookbook/form/form_collections.html

2.此外,你需要一个单向多对多。为什么?您正在任务内分配标签,而不是相反。另外,也许你需要标记其他实体。

有关多对多(单向)文档看看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; 

标签实体

保护$任务;


注意:当您从任务中删除标签,并没有其他的任务是使用你删除一个标签,标签将被保留为“孤儿”。在ManyToMany关系中,Doctrine不能很好地处理孤儿删除问题,因此您必须手动删除这些孤儿。或者,您可以将标签放置在未使用的位置,稍后再添加。

+0

最后!无眠一周后,设法找到解决方案..仍不知道为什么,但ajax调用提交按钮打破了collectiontype..somehow ..我接受这个答案,事件并没有解决我的问题,但很好地解释和改进。 :) – Degu