我正在尝试通过单个表单提交将用户实体与配置文件实体保持一致。按照Doctrine2 文档中的说明并添加其他属性后,这似乎足以实现目标。
实体
按照规定设置实体非常简单,结果如下(我省略了生成的 getter/setter):
// ...
/**
* @ORM\Entity
*/
class User
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue
*/
private $id;
/**
* @ORM\Column(type="string", length=64)
*/
private $data;
/**
* @ORM\OneToOne(targetEntity="Profile", mappedBy="user", cascade={"persist", "remove"})
*/
private $Profile;
// ...
}
// ...
/**
* @ORM\Entity
*/
class Profile
{
/**
* @ORM\Id
* @ORM\OneToOne(targetEntity="User")
*/
private $user;
/**
* @ORM\Column(type="string", length=64)
*/
private $data;
// ...
}
形式
现在修改表格也不太难:
// ...
class ProfileType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('data')
;
}
public function getName()
{
return 'profile';
}
public function getDefaultOptions(array $options)
{
return array('data_class' => 'Acme\TestBundle\Entity\Profile');
}
}
// ...
class TestUserType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('data')
->add('Profile', new ProfileType())
;
}
public function getName()
{
return 'user';
}
}
控制器
class UserController extends Controller
{
// ...
public function newAction()
{
$entity = new User();
$form = $this->createForm(new UserType(), $entity);
return array(
'entity' => $entity,
'form' => $form->createView()
);
}
public function createAction()
{
$entity = new User();
$request = $this->getRequest();
$form = $this->createForm(new UserType(), $entity);
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('user_show',
array('id' => $entity->getId())));
}
return array(
'entity' => $entity,
'form' => $form->createView()
);
}
// ...
}
但现在是进行测试的部分。我开始创建一个新的用户对象,嵌入的表单按预期显示,但点击提交返回:
例外
Acme\TestBundle\Entity\Profile 类型的实体缺少分配的 ID。此实体的标识符生成策略要求在调用 EntityManager#persist() 之前填充 ID 字段。如果您想要自动生成标识符,则需要相应地调整元数据映射。
我已经知道的一个可能的解决方案是为 Profile 实体上的独立主键添加一个附加列。
但是我想知道是否有一种方法可以使映射保持大致相同但处理保留嵌入式表单?