Php 实体';SonataAdmin中的OneToMany关系中未保存父项的id
我使用SonataAdmin(和Symfony2)来管理我的实体。我在一个步骤和许多任务之间有一种单一的关系。因为一个步骤可以包含许多任务,所以当我创建一个步骤时,我希望能够创建许多任务,并且希望这些任务链接到此步骤。为此,我创建了所有适当的管理类(一个用于任务,一个用于步骤) 这就是我所做的导致我的问题的事情。当我尝试创建一个步骤时,我可以创建任务,甚至可以对它们重新排序,这非常好,所有这些都是由SonataAdminBundle自动完成的。当我单击save时,所有内容都保存在数据库中,但在数据库中,步骤的id没有设置在任务的行中。因此,任务未链接到步骤 这是我的Step管理类:Php 实体';SonataAdmin中的OneToMany关系中未保存父项的id,php,symfony,sonata-admin,Php,Symfony,Sonata Admin,我使用SonataAdmin(和Symfony2)来管理我的实体。我在一个步骤和许多任务之间有一种单一的关系。因为一个步骤可以包含许多任务,所以当我创建一个步骤时,我希望能够创建许多任务,并且希望这些任务链接到此步骤。为此,我创建了所有适当的管理类(一个用于任务,一个用于步骤) 这就是我所做的导致我的问题的事情。当我尝试创建一个步骤时,我可以创建任务,甚至可以对它们重新排序,这非常好,所有这些都是由SonataAdminBundle自动完成的。当我单击save时,所有内容都保存在数据库中,但在数
<?php
// src/Acme/DemoBundle/Admin/PostAdmin.php
namespace IMA\ProcessManagementBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
class StepAdmin extends Admin
{
// Fields to be shown on create/edit forms
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name', 'text', array('label' => 'Nom de l\'étape'))
->add('tasks', 'sonata_type_collection', array(), array(
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'positionNumber'
))
->add('positionNumber', 'integer', array('label' => 'Position'))
;
}
// Fields to be shown on filter forms
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('name')
;
}
// Fields to be shown on lists
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
->add('slug')
;
}
}
<?php
// src/Acme/DemoBundle/Admin/PostAdmin.php
namespace IMA\ProcessManagementBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
class TaskAdmin extends Admin
{
// Fields to be shown on create/edit forms
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name', 'text', array('label' => 'Tâche'))
->add('positionNumber', 'integer', array('label' => 'Position'))
;
}
// Fields to be shown on filter forms
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('name')
;
}
// Fields to be shown on lists
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
->add('slug')
;
}
}
我想知道为什么没有在任务行中设置步骤的id…在您的
步骤
实体中,您必须在addTask方法中添加:
class Step
{
//...
public function addTask($tasks)
{
$tasks->setStep($this);
$this->tasks[] = $tasks;
return $this;
}
//...
}
由于您尚未给出
Step.php
,因此您应该适当地修改此代码。您需要手动将步骤附加到任务,为此,您需要使用Step admin类中的prePersist和preUpdate方法
原因是SonataAdminBundle的开发人员表示,处理这一问题是原则的考虑,原则开发人员表示,这是捆绑包的责任。。。所以现在我们需要自己去做
这将是您的新stepAdmin类:
<?php
namespace IMA\ProcessManagementBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
class StepAdmin extends Admin
{
// Fields to be shown on create/edit forms
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name', 'text', array('label' => 'Nom de l\'étape'))
->add('tasks', 'sonata_type_collection', array(), array(
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'positionNumber'
))
->add('positionNumber', 'integer', array('label' => 'Position'))
;
}
// Fields to be shown on filter forms
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('name')
;
}
// Fields to be shown on lists
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
->add('slug')
;
}
public function prePersist($object)
{
foreach ($object->getTasks() as $task) {
$task->setStep($object);
}
}
public function preUpdate($object)
{
foreach ($object->getTasks() as $task) {
$task->setStep($object);
}
}
}
由于我指定了多人和一人的关系,这不是正常自动完成的吗?不,这不是自动完成的。在新请求中可能会出现这种情况,因为随后将从数据库中提取实体(一切都会井然有序)。在以下情况下,这会给您带来麻烦,如果您创建新步骤并尝试添加任务,则会出现以下错误:“传递到选项字段的实体必须进行管理”。这是因为您将以“$This”作为参数调用“setStep”,但该实体尚未持久化。在我上面的示例中,这个问题没有出现,因为您的实体已准备好插入,并且您已经“管理”了实体。app/console原则:schema:validate
告诉您什么?在将新的步骤添加到任务中时,可能会重复此操作,但不用于删除步骤!实际上,preUpdate()
函数不知道删除哪个步骤,因为前面的情况未知,因为$object->getTasks()
给出了已验证表单的情况。怎么解决?我所做的就是使用条令快照。在集合中,调用getSnapshot(),然后将两者进行比较。也许这不是最好的方法。@Blacksad:不知道它是否仍然相关,但请尝试在@ORM\OneToMany()
选项中指定。这为我解决了相关实体移除问题。谢谢@geert wille!今天救了我:)
<?php
namespace IMA\ProcessManagementBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
class StepAdmin extends Admin
{
// Fields to be shown on create/edit forms
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name', 'text', array('label' => 'Nom de l\'étape'))
->add('tasks', 'sonata_type_collection', array(), array(
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'positionNumber'
))
->add('positionNumber', 'integer', array('label' => 'Position'))
;
}
// Fields to be shown on filter forms
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('name')
;
}
// Fields to be shown on lists
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
->add('slug')
;
}
public function prePersist($object)
{
foreach ($object->getTasks() as $task) {
$task->setStep($object);
}
}
public function preUpdate($object)
{
foreach ($object->getTasks() as $task) {
$task->setStep($object);
}
}
}