现在我在表单中提交帖子数据时遇到问题(我的表单如下所示:
Task: <input text>
Category: <multiple select category>
DueDate: <date>
<submit>
)提交表单后,我会收到此错误:
Found entity of type Doctrine'Common'Collections'ArrayCollection on association Acme'TaskBundle'Entity'Task#category, but expecting Acme'TaskBundle'Entity'Category
我的来源:
任务对象 任务.php
<?php
namespace Acme'TaskBundle'Entity;
use Doctrine'ORM'Mapping as ORM;
use Symfony'Component'Validator'Constraints as Assert;
/**
* @ORM'Entity
* @ORM'Table(name="tasks")
*/
class Task
{
/**
* @ORM'Id
* @ORM'Column(type="integer")
* @ORM'GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM'Column(type="string", length=200)
* @Assert'NotBlank(
* message = "Task cannot be empty"
* )
* @Assert'Length(
* min = "3",
* minMessage = "Task is too short"
* )
*/
protected $task;
/**
* @ORM'Column(type="datetime")
* @Assert'NotBlank()
* @Assert'Type("'DateTime")
*/
protected $dueDate;
/**
* @Assert'True(message = "You have to agree")
*/
protected $accepted;
/**
* @ORM'ManyToMany(targetEntity="Category", inversedBy="tasks")
*/
protected $category;
/**
* Constructor
*/
public function __construct()
{
$this->category = new 'Doctrine'Common'Collections'ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set task
*
* @param string $task
* @return Task
*/
public function setTask($task)
{
$this->task = $task;
return $this;
}
/**
* Get task
*
* @return string
*/
public function getTask()
{
return $this->task;
}
/**
* Set dueDate
*
* @param 'DateTime $dueDate
* @return Task
*/
public function setDueDate($dueDate)
{
$this->dueDate = $dueDate;
return $this;
}
/**
* Get dueDate
*
* @return 'DateTime
*/
public function getDueDate()
{
return $this->dueDate;
}
/**
* Add category
*
* @param 'Acme'TaskBundle'Entity'Category $category
* @return Task
*/
public function addCategory('Acme'TaskBundle'Entity'Category $category)
{
$this->category[] = $category;
return $this;
}
/**
* Remove category
*
* @param 'Acme'TaskBundle'Entity'Category $category
*/
public function removeCategory('Acme'TaskBundle'Entity'Category $category)
{
$this->category->removeElement($category);
}
/**
* Get category
*
* @return 'Doctrine'Common'Collections'Collection
*/
public function getCategory()
{
return $this->category;
}
}
类别对象类别.php
<?php
namespace Acme'TaskBundle'Entity;
use Doctrine'ORM'Mapping as ORM;
use Symfony'Component'Validator'Constraints as Assert;
/**
* @ORM'Entity
* @ORM'Table(name="categories")
*/
class Category
{
/**
* @ORM'Id
* @ORM'Column(type="integer")
* @ORM'GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM'Column(type="string", length=200, unique=true)
* @Assert'NotNull(message="Choose a category", groups = {"adding"})
*/
protected $name;
/**
* @ORM'ManyToMany(targetEntity="Task", mappedBy="category")
*/
private $tasks;
public function __toString()
{
return strval($this->name);
}
/**
* Constructor
*/
public function __construct()
{
$this->tasks = new 'Doctrine'Common'Collections'ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return Category
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Add tasks
*
* @param 'Acme'TaskBundle'Entity'Task $tasks
* @return Category
*/
public function addTask('Acme'TaskBundle'Entity'Task $tasks)
{
$this->tasks[] = $tasks;
return $this;
}
/**
* Remove tasks
*
* @param 'Acme'TaskBundle'Entity'Task $tasks
*/
public function removeTask('Acme'TaskBundle'Entity'Task $tasks)
{
$this->tasks->removeElement($tasks);
}
/**
* Get tasks
*
* @return 'Doctrine'Common'Collections'Collection
*/
public function getTasks()
{
return $this->tasks;
}
}
任务类型 任务类型.php
<?php
namespace Acme'TaskBundle'Form'Type;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
use Acme'TaskBundle'Form'Type'Category;
class TaskType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme'TaskBundle'Entity'Task',
'cascade_validation' => true,
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('task', 'text', array('label' => 'Task'))
->add('dueDate', 'date', array('label' => 'Due Date'))
->add('category', new CategoryType(), array('validation_groups' => array('adding')))
//->add('accepted', 'checkbox')
->add('save', 'submit', array('label' => 'Submit'));
}
public function getName()
{
return 'task';
}
}
类别类型 类别类型.php
<?php
namespace Acme'TaskBundle'Form'Type;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
class CategoryType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => null,
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', 'entity', array(
'class' => 'AcmeTaskBundle:Category',
'query_builder' => function($repository) { return $repository->createQueryBuilder('c')->orderBy('c.id', 'ASC'); },
'property' => 'name',
'multiple' => true,
'label' => 'Categories',
));
}
public function getName()
{
return 'category';
}
}
和我的控制器默认控制器.php:
public function newAction(Request $request)
{
$task = new Task();
$task->setTask('Write name here...');
$task->setDueDate(new 'DateTime('tomorrow'));
$form = $this->createForm('task', $task);
$form->handleRequest($request);
if($form->isValid())
{
$this->get('session')->getFlashBag()->add(
'success',
'Task was successfuly created'
);
$em = $this->getDoctrine()->getManager();
/*
$category = $this->getDoctrine()->getManager()->getRepository('AcmeTaskBundle:Category')->findOneByName($form->get('category')->getData());
$task->setCategory($category);
*/
$em->persist($task);
try {
$em->flush();
} catch ('PDOException $e) {
// sth
}
//$nextAction = $form->get('saveAndAdd')->isClicked() ? 'task_new' : 'task_success';
//return $this->redirect($this->generateUrl($nextAction));
}
return $this->render('AcmeTaskBundle:Default:new.html.twig', array('form' => $form->createView()));
}
所以,我在谷歌上看了这个问题,但有不同类型的问题。知道吗?
更新完整的错误消息:
[2013-09-30 14:43:55] request.CRITICAL: Uncaught PHP Exception Doctrine'ORM'ORMException: "Found entity of type Doctrine'Common'Collections'ArrayCollection on association Acme'TaskBundle'Entity'Task#category, but expecting Acme'TaskBundle'Entity'Category" at /var/www/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 762 {"exception":"[object] (Doctrine''ORM''ORMException: Found entity of type Doctrine''Common''Collections''ArrayCollection on association Acme''TaskBundle''Entity''Task#category, but expecting Acme''TaskBundle''Entity''Category at /var/www/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:762)"} []
更新 2
我的树枝模板新.html.twig
<html>
<head>
<title>Task create</title>
</head>
<body>
{% for flashMessage in app.session.flashbag.get('success') %}
<div style="display: block; padding: 15px; border: 1px solid green; margin: 15px; width: 450px;">
{{ flashMessage }}
</div>
{% endfor %}
{{ form_start(form, {'action': path ('task_new'), 'method': 'POST', 'attr': {'novalidate': 'novalidate' }}) }}
{{ form_errors(form) }}
<div>
{{ form_label(form.task) }}:<br>
{{ form_widget(form.task) }} {{ form_errors(form.task) }}<br>
</div>
<div>
{{ form_label(form.category) }}:<br>
{{ form_widget(form.category) }} {{ form_errors(form.category) }}
</div>
<div>
{{ form_label(form.dueDate) }}:<br>
{{ form_widget(form.dueDate) }} {{ form_errors(form.dueDate) }}<br>
</div>
{{ form_end(form) }}
</body>
</html>
您可以通过更改实体中的资源库来改进控制器代码:
在Task
:
public function addCategory(Category $category)
{
if (!$this->categories->contains($category)) {
$this->categories->add($category);
$category->addTask($this); // Fix this
}
}
在Category
:
public function addTask(Task $task)
{
if (!this->tasks->contains($task)) {
$this->tasks->add($task);
$task->addCategory($this);
}
}
这将使ArrayCollection
中的元素保持唯一,因此您不必在代码中执行该检查,并且还会自动设置反面。
所以我找到了我的解决方案!此代码有效:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('task', 'text', array('label' => 'Task'))
->add('dueDate', 'date', array('label' => 'Date', 'format' => 'ddMMMMyyyy'))
->add('category', 'entity', array('required' => true, 'multiple' => true, 'class' => 'AcmeTaskBundle:Category', 'query_builder' => function($repository) { return $repository->createQueryBuilder('c')->orderBy('c.id', 'ASC'); },))
->add('save', 'submit', array('label' => 'Send'));
}
我的控制器以这种形式工作:
if($form->isValid())
{
$this->get('session')->getFlashBag()->add(
'success',
'Task successfuly added'
);
$em = $this->getDoctrine()->getManager();
foreach($form->get('category')->getData() as $cat)
{
$task->removeCategory($cat);
$task->addCategory($cat);
}
$em->persist($task);
try {
$em->flush();
} catch ('PDOException $e) {
// sth
}
}
我被迫使用$task->removeCategory($cat)
因为如果它不在这里,我会得到配音主索引的错误。
现在我正在尝试解决嵌入式和非嵌入式表单的问题 -> Symfony2,验证具有相同参数和不同结果的嵌入式和非嵌入式表单?
我相信我的问题对Symfony2有同样问题的初学者很有帮助。
您正在定义从任务到类别的多对多关系,这意味着每个任务可以有多个类别。如果您尝试在一个任务中包含多个类别,可以尝试更改此行
->add('category', new CategoryType(), array('validation_groups' => array('adding')))
对于类似的东西
->add('category', 'collection', array('type' => new CategoryType()))
查看Symfony关于表单收集的文档和这本食谱
我不确定,但请尝试将 setCategory 方法添加到您的 Task 实体,因为目前您只有 add 函数,这就是为什么表单组件调用 addFunction 而不是整个数组集合的集合。
我认为你的形式有问题。
您的任务与分类具有多对多关系,并存储在字段category
中(逻辑上它是一个类别)。但是在你设置的形式中,你设置了'->add('category',new CategoryType())',这意味着你添加了一个新的类型,它是一个数组或其他东西(data_class未定义),并且这个类型包含另一个字段。
解决方案是直接定义表单中的字段(不使用独立表单类型)或从实体类型扩展类别表单类型(默认类型扩展表单类型)。