当我使用 sonata_type_admin 嵌入实体时,构造或验证不起作用
Construct or validation does not work when I embed an entity with sonata_type_admin
我有一个实体 'Employee',我嵌入了一个具有 'sonata_type_admin' 表单类型(一对一关系)的实体 'User'。
当我创建一个新的 Employee 对象时,我想将默认值设置为 User 对象,但是从不调用 User __construct() 或 getNewInstance() 方法。
我还注意到,当我编辑员工时,用户验证约束不起作用(例如,如果我编辑员工并尝试设置已经存在的用户名,验证约束不会显示在用户名字段上)。如果我编辑用户,__construct()、getNewInstance() 和验证约束工作正常。
我能做什么?
我从 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>
我的员工实体在 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;
...
我的 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"
为了进行验证,您必须在 Employee 实体上添加约束才能使 $user 属性 有效。
http://symfony.com/doc/current/reference/constraints/Valid.html
如果坚持也有问题,可能是因为您在员工管理员中存在双向关系,在 preUpdate/prePersist(这些是管理员知道的功能)上,您还必须 link 员工通过做类似的事情给用户:
public function prePersist($object) {
$object->getUser()->setEmployee($object);
}
或者,您可以尝试仅将用户映射到员工(不使用 inversedBy 指令)。
终于,我找到了解决方案(@anegrea 感谢您的帮助)。
Sonata 不会在 Employee create 上调用 User 构造,因为它不知道它是否可以为空(如果创建用户则不同,因为用户是必需的)。如果你想在 Employee create 上调用 User 构造,你必须将数据放在相关字段上。
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()
;
}
...
}
另一方面,为了在创建或编辑员工时在用户字段上显示错误,我必须在员工实体中的用户映射上添加有效约束,并在员工管理中添加与 FOSUserBundle 相关的验证组。
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;
}
...
}
我有一个实体 'Employee',我嵌入了一个具有 'sonata_type_admin' 表单类型(一对一关系)的实体 'User'。 当我创建一个新的 Employee 对象时,我想将默认值设置为 User 对象,但是从不调用 User __construct() 或 getNewInstance() 方法。 我还注意到,当我编辑员工时,用户验证约束不起作用(例如,如果我编辑员工并尝试设置已经存在的用户名,验证约束不会显示在用户名字段上)。如果我编辑用户,__construct()、getNewInstance() 和验证约束工作正常。
我能做什么?
我从 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>
我的员工实体在 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;
...
我的 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"
为了进行验证,您必须在 Employee 实体上添加约束才能使 $user 属性 有效。 http://symfony.com/doc/current/reference/constraints/Valid.html
如果坚持也有问题,可能是因为您在员工管理员中存在双向关系,在 preUpdate/prePersist(这些是管理员知道的功能)上,您还必须 link 员工通过做类似的事情给用户:
public function prePersist($object) {
$object->getUser()->setEmployee($object);
}
或者,您可以尝试仅将用户映射到员工(不使用 inversedBy 指令)。
终于,我找到了解决方案(@anegrea 感谢您的帮助)。
Sonata 不会在 Employee create 上调用 User 构造,因为它不知道它是否可以为空(如果创建用户则不同,因为用户是必需的)。如果你想在 Employee create 上调用 User 构造,你必须将数据放在相关字段上。
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()
;
}
...
}
另一方面,为了在创建或编辑员工时在用户字段上显示错误,我必须在员工实体中的用户映射上添加有效约束,并在员工管理中添加与 FOSUserBundle 相关的验证组。
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;
}
...
}