I'm using SonataAdmin (and Symfony2) to manage my entities. I have a oneToMany relationship between one Step and many Tasks. Since one Step can contain many Tasks, when I create a Step, I want to be able to create many Tasks and I want those tasks to be linked to this Step. To do so, I created all the proper admin classes (one for Task and one for Step).
Here's what I do that causes my problem. When I try to create a Step, I can create the tasks and even reorder them, which is great and all done automatically by SonataAdminBundle. When I click on save, everything is saved in the database, except that in the database, the id of the step is not set in the row of the Task. Therefore, the tasks are not linked to the Step...
Here's my Step's admin class:
<?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')
;
}
}
Here's also my Task admin class:
<?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')
;
}
}
Also, here are the description of my entities
IMA\ProcessManagementBundle\Entity\Step:
type: entity
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
name:
type: string
length: 255
positionNumber:
type: integer
oneToMany:
tasks:
targetEntity: Task
mappedBy: step
cascade: ["persist", "merge"]
lifecycleCallbacks: { }
IMA\ProcessManagementBundle\Entity\Task:
type: entity
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
name:
type: string
length: 255
positionNumber:
type: integer
manyToOne:
step:
targetEntity: Step
inversedBy: tasks
lifecycleCallbacks: { }
I'm wondering why the id of the Step is not set in the Task row...
You need to manually attach the step to the tasks, to do so you need to use the prePersist and preUpdate methods in the step admin class...
The reason for this is that the developers of the SonataAdminBundle say it's doctrine's concern to handle this and the Doctrine developers say it is the bundles responsibility... So for now we need to do it for ourselves.
This would be your new stepAdmin class:
<?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);
}
}
}
In your Step
entity you have to add in the addTask method :
class Step
{
//...
public function addTask($tasks)
{
$tasks->setStep($this);
$this->tasks[] = $tasks;
return $this;
}
//...
}
As you haven't give your Step.php
you should propably adapt this code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With