symfony3:为具有多对一关系列的实体创建表单
symfony3: create form for entity that has a column with many to one relationship
我有一个 "Tasks" table 引用了一个 "Estados" table 和从列 Tasks.taskestado 到 Estados.estado 的外键。
这是任务的相关 XML 映射:
<entity name="AppBundle\Entity\Tasks" table="TASKS" repository-class="AppBundle\Repository\TasksRepository">
<id name="taskid" type="bigint" column="TaskID">
<generator strategy="IDENTITY"/>
</id>
...
<many-to-one field="taskestado" target-entity="Estados" fetch="LAZY">
<join-columns>
<join-column name="TaskEstado" referenced-column-name="Estado"/>
</join-columns>
</many-to-one>
...
对于 Estados:
<entity name="AppBundle\Entity\Estados" table="ESTADOS">
<id name="estado" type="string" column="Estado" length="15">
<generator strategy="IDENTITY"/>
</id>
<field name="estadodescricao" type="string" column="EstadoDescricao" length="50" nullable="true">
<options>
<option name="fixed"/>
</options>
</field>
...
鉴于此,我正在尝试执行一个操作 (novaAction()) 来创建任务。
这是控制器代码:
public function novaAction(Request $request)
{
$task = new Tasks();
$em = $this->getDoctrine()->getManager();
dump($task);
#$task->setTaskEstado(new Estados());
$form = $this->createForm(TasksType::class, $task);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
// Criar a tarefa na BD
$em->persist($form->getData());
$em->flush();
$this->addFlash('notice', 'app.nova_tarefa.mensagem_sucesso');
return $this->redirectToRoute('nova_tarefa');
}
$this->addFlash('error', 'app.nova_tarefa.mensagem_erro');
}
以及相关的TasksType代码:
class TasksType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('taskid', HiddenType::class)
...
#->add('taskestado')
->add('taskestado', EntityType::class, [ 'class' => 'AppBundle:Estados' ])
...
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Tasks',
#'empty_data' => function (\Symfony\Component\Form\FormInterface $form) {
# #return new Tasks($form->get('tasks')->getData());
# return new Tasks();
#},
));
}
}
'empty_data' 选项试图在不向其传递任务实例的情况下创建表单。
此外,当我使用注释代码添加 taskestado 时,我得到了相同的结果,我。即,没有参数。
这是相关的任务实体:
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Tasks
*/
class Tasks
{
/**
* @var integer
*/
protected $taskid;
/**
* @var \AppBundle\Entity\Estados
*/
protected $taskestado;
...
/**
* Get taskid
*
* @return integer
*/
public function getTaskid()
{
return $this->taskid;
}
/**
* Set taskestado
*
* @param \AppBundle\Entity\Estados $taskestado
*
* @return Tasks
*/
public function setTaskestado(\AppBundle\Entity\Estados $taskestado = null)
{
$this->taskestado = $taskestado;
return $this;
}
/**
* Get taskestado
*
* @return \AppBundle\Entity\Estados
*/
public function getTaskestado()
{
return $this->taskestado;
}
...
}
当我打开页面时,出现以下错误:
Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
我还生成了 CRUD (bin/console doctrine:generate:crud --filter=Tasks
),这样我就可以检查它是如何完成的,但是代码和结果是相似的(在修复了一些 TasksType 中的一些问题之后日期时间列)。
我做错了什么?
如错误所述,您需要在任务映射中设置 cascade = persist。例如:
<many-to-one field="taskestado" target-entity="Estados" fetch="LAZY">
<cascade>
<cascade-persist/>
</cascade>
<join-columns>
<join-column name="TaskEstado" referenced-column-name="Estado"/>
</join-columns>
</many-to-one>
也不是做$em->persist($form->getData());
使用 $em->persist($task);
看看是否可行...
确保你有
$this->taskestado = new ArrayCollection();
在您的 Tasks
class 的 __construct()
中。
然后2条通知:
尽量在代码中只使用英语。这样你会得到更多的回应。
作为 "best practise" 为您的实体 class 名称使用单数,例如 Task
、TaskEstado
我终于得到了答案,它远非显而易见。
正如我在问题中所说,从 Tasks.taskestado 到 Estados.estado 存在 many-to-one 关系。 Estados.estado 是一个字符串,可以为空,一个空字符串或(通常)一个 non-empty 字符串。虽然未在映射中指明,但空字符串是 taskestado 的默认值。
我已经有关于 table 的数据,而 Estados.estado 的条目之一恰好是空字符串。
我在问题中没有post,但我在这个异常的堆栈跟踪中看到了以下信息:
[1] Symfony\Component\Form\Exception\RuntimeException: Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
at n/a
in /var/www/simpletask2/vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php line 119
at Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader->getIdValue(object(Estados))
in line
at call_user_func(array(object(IdReader), 'getIdValue'), object(Estados))
in /var/www/simpletask2/vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php line 204
at Symfony\Component\Form\ChoiceList\ArrayChoiceList->flatten(array(object(Estados), object(Estados), object(Estados), object(Estados), object(Estados), object(Estados), object(Estados), object(Estados)), array(object(IdReader), 'getIdValue'), array(), array(), array())
in /var/www/simpletask2/vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php line 91
因此,EntityType 从数据库中检索了值并尝试呈现它们。换句话说,它们已经存在,问题可能不在于我如何初始化实体。
因此,我想起了 Estados 实体的空字符串值,并尝试将其从数据库中删除:问题已解决,TaskEstado 实体已按预期初始化和呈现。
现在我需要一种方法来解决这个问题,但找到了解决方案。
感谢大家的回答。
我有一个 "Tasks" table 引用了一个 "Estados" table 和从列 Tasks.taskestado 到 Estados.estado 的外键。
这是任务的相关 XML 映射:
<entity name="AppBundle\Entity\Tasks" table="TASKS" repository-class="AppBundle\Repository\TasksRepository">
<id name="taskid" type="bigint" column="TaskID">
<generator strategy="IDENTITY"/>
</id>
...
<many-to-one field="taskestado" target-entity="Estados" fetch="LAZY">
<join-columns>
<join-column name="TaskEstado" referenced-column-name="Estado"/>
</join-columns>
</many-to-one>
...
对于 Estados:
<entity name="AppBundle\Entity\Estados" table="ESTADOS">
<id name="estado" type="string" column="Estado" length="15">
<generator strategy="IDENTITY"/>
</id>
<field name="estadodescricao" type="string" column="EstadoDescricao" length="50" nullable="true">
<options>
<option name="fixed"/>
</options>
</field>
...
鉴于此,我正在尝试执行一个操作 (novaAction()) 来创建任务。 这是控制器代码:
public function novaAction(Request $request)
{
$task = new Tasks();
$em = $this->getDoctrine()->getManager();
dump($task);
#$task->setTaskEstado(new Estados());
$form = $this->createForm(TasksType::class, $task);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
// Criar a tarefa na BD
$em->persist($form->getData());
$em->flush();
$this->addFlash('notice', 'app.nova_tarefa.mensagem_sucesso');
return $this->redirectToRoute('nova_tarefa');
}
$this->addFlash('error', 'app.nova_tarefa.mensagem_erro');
}
以及相关的TasksType代码:
class TasksType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('taskid', HiddenType::class)
...
#->add('taskestado')
->add('taskestado', EntityType::class, [ 'class' => 'AppBundle:Estados' ])
...
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Tasks',
#'empty_data' => function (\Symfony\Component\Form\FormInterface $form) {
# #return new Tasks($form->get('tasks')->getData());
# return new Tasks();
#},
));
}
}
'empty_data' 选项试图在不向其传递任务实例的情况下创建表单。 此外,当我使用注释代码添加 taskestado 时,我得到了相同的结果,我。即,没有参数。
这是相关的任务实体:
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Tasks
*/
class Tasks
{
/**
* @var integer
*/
protected $taskid;
/**
* @var \AppBundle\Entity\Estados
*/
protected $taskestado;
...
/**
* Get taskid
*
* @return integer
*/
public function getTaskid()
{
return $this->taskid;
}
/**
* Set taskestado
*
* @param \AppBundle\Entity\Estados $taskestado
*
* @return Tasks
*/
public function setTaskestado(\AppBundle\Entity\Estados $taskestado = null)
{
$this->taskestado = $taskestado;
return $this;
}
/**
* Get taskestado
*
* @return \AppBundle\Entity\Estados
*/
public function getTaskestado()
{
return $this->taskestado;
}
...
}
当我打开页面时,出现以下错误:
Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
我还生成了 CRUD (bin/console doctrine:generate:crud --filter=Tasks
),这样我就可以检查它是如何完成的,但是代码和结果是相似的(在修复了一些 TasksType 中的一些问题之后日期时间列)。
我做错了什么?
如错误所述,您需要在任务映射中设置 cascade = persist。例如:
<many-to-one field="taskestado" target-entity="Estados" fetch="LAZY">
<cascade>
<cascade-persist/>
</cascade>
<join-columns>
<join-column name="TaskEstado" referenced-column-name="Estado"/>
</join-columns>
</many-to-one>
也不是做$em->persist($form->getData());
使用 $em->persist($task);
看看是否可行...
确保你有
$this->taskestado = new ArrayCollection();
在您的 Tasks
class 的 __construct()
中。
然后2条通知:
尽量在代码中只使用英语。这样你会得到更多的回应。
作为 "best practise" 为您的实体 class 名称使用单数,例如 Task
、TaskEstado
我终于得到了答案,它远非显而易见。
正如我在问题中所说,从 Tasks.taskestado 到 Estados.estado 存在 many-to-one 关系。 Estados.estado 是一个字符串,可以为空,一个空字符串或(通常)一个 non-empty 字符串。虽然未在映射中指明,但空字符串是 taskestado 的默认值。
我已经有关于 table 的数据,而 Estados.estado 的条目之一恰好是空字符串。
我在问题中没有post,但我在这个异常的堆栈跟踪中看到了以下信息:
[1] Symfony\Component\Form\Exception\RuntimeException: Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
at n/a
in /var/www/simpletask2/vendor/symfony/symfony/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php line 119
at Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader->getIdValue(object(Estados))
in line
at call_user_func(array(object(IdReader), 'getIdValue'), object(Estados))
in /var/www/simpletask2/vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php line 204
at Symfony\Component\Form\ChoiceList\ArrayChoiceList->flatten(array(object(Estados), object(Estados), object(Estados), object(Estados), object(Estados), object(Estados), object(Estados), object(Estados)), array(object(IdReader), 'getIdValue'), array(), array(), array())
in /var/www/simpletask2/vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php line 91
因此,EntityType 从数据库中检索了值并尝试呈现它们。换句话说,它们已经存在,问题可能不在于我如何初始化实体。
因此,我想起了 Estados 实体的空字符串值,并尝试将其从数据库中删除:问题已解决,TaskEstado 实体已按预期初始化和呈现。
现在我需要一种方法来解决这个问题,但找到了解决方案。
感谢大家的回答。