Reputation: 11
I have an entity 'Employee' and I embed an entity 'User' with 'sonata_type_admin' form type (one to one relation). When I create a new Employee object I want to set default values to User object, but User __construct() or getNewInstance() method is never called. I also noticed that user validation constraints don't work when I edit an Employee (for instance, if I edit an employee and I try to set an username that already exists, validation constraint is not displayed on username field). If I edit an user, __construct(), getNewInstance() and validation constraints works fine.
What can I do?
I extended my user entity from SonataUserBundle (FOSUserBundle).
//User.orm.xml
...
<entity name="Application\Sonata\UserBundle\Entity\User" table="fos_user_user">
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
<one-to-one field="employee" target-entity="AppBundle\Entity\Employee" mapped-by="user" />
</entity>
</doctrine-mapping>
My Employee entity is in AppBundle.
//Employee.php
namespace AppBundle\Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Timestampable\Traits\TimestampableEntity;
use Doctrine\ORM\Mapping as ORM;
/**
* Session
*
* @ORM\Table(name="nup_employee")
* @ORM\Entity(repositoryClass="AppBundle\Entity\EmployeeRepository")
*/
class Employee
{
const STATUS_INACTIVE = 0;
const STATUS_ACTIVE = 1;
use TimestampableEntity;
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\OneToOne(
* targetEntity="Application\Sonata\UserBundle\Entity\User",
* inversedBy="employee",
* cascade={"persist", "remove"}
* )
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
private $user;
...
My configureFormFields.
//UserAdmin.php
...
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('General')
->add('username')
->add('email')
->add('plainPassword', 'text', array(
'required' => (!$this->getSubject() || is_null($this->getSubject()->getId()))
))
->end()
;
$formMapper
->with('Security')
->add('enabled', null, array('required' => false))
->add('locked', null, array('required' => false))
->add('token', null, array('required' => false))
->add('twoStepVerificationCode', null, array('required' => false))
->end()
;
}
...
Composer.json:
...
"symfony/symfony": "2.7.*",
...
"friendsofsymfony/user-bundle": "~1.3",
"sonata-project/admin-bundle": "2.3.*",
"sonata-project/doctrine-orm-admin-bundle": "2.3.*",
"sonata-project/user-bundle": "^2.2"
Upvotes: 0
Views: 1230
Reputation: 11
Finally, I found the solution (@anegrea thanks for your help).
Sonata doesn't call User construct on Employee create because it doesn't know if it's nullable or not (it's different if you create a user because the user is required). if you want to call User construct on Employee create you have to put data on related field.
class EmployeeAdmin extends Admin
{
...
protected function configureFormFields(FormMapper $formMapper)
{
$data = new User();
if ($this->getSubject()->getUser()) {
$data = $this->getSubject()->getUser();
}
$formMapper
->with('General', array('class' => 'col-md-6'))
->add('name')
->add('surnames')
->end()
->with('Access', array('class' => 'col-md-6'))
->add('user', 'sonata_type_admin',
array(
'data' => $data,
'label' => false
),
array(
'admin_code' => 'sonata.user.admin.user',
'edit' => 'inline'
)
)
->end()
;
}
...
}
On the other hand, to show errors on User fields when I create or edit an Employee, I had to add Valid constraint on user mapping in Employee entity and add validation groups related to FOSUserBundle in EmployeeAdmin.
class Employee
{
...
/**
* @ORM\OneToOne(
* targetEntity="Application\Sonata\UserBundle\Entity\User",
* inversedBy="employee",
* cascade={"persist", "remove"}
* )
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
* @Assert\Valid
*/
private $user;
...
}
class EmployeeAdmin extends Admin
{
public function getFormBuilder()
{
$this->formOptions['data_class'] = $this->getClass();
$options = $this->formOptions;
$options['validation_groups'] = array('Default');
array_push($options['validation_groups'], (!$this->getSubject() || is_null($this->getSubject()->getId())) ? 'Registration' : 'Profile');
$formBuilder = $this->getFormContractor()->getFormBuilder($this->getUniqid(), $options);
$this->defineFormBuilder($formBuilder);
return $formBuilder;
}
...
}
Upvotes: 1
Reputation: 1192
For the validation you have to add the constraint on the Employee entity for the $user property to be Valid. http://symfony.com/doc/current/reference/constraints/Valid.html
If there is a problem with persisting also, it might be because you are having the bidirectional relation that in you employee admin, on preUpdate/prePersist (these are funcitons the admin knows about) you must also link the employee to the user by doing something like:
public function prePersist($object) {
$object->getUser()->setEmployee($object);
}
Or, you can try to have only the user mapped on the employee (without the inversedBy directve).
Upvotes: 0