首先,我不确定这是 Sonata 问题还是 Symfony2 的问题。这是我第一次使用 Sf2 表单来编辑关系。以下是问题描述:
我有两个类,我们简称为 "Car" 和 "Wheel"。 "Car" 可以选择性地与 "Wheel" 建立一对一的关系(这只是一个示例,请跟着走...)。我已经设置了 SonataAdmin,使用 "sonata_type_admin" 将 "WheelAdmin" 内嵌到 "CarAdmin" 中,并尝试创建一辆汽车,而没有输入任何与 "Wheel" 相关的数据。
然而,在提交表单时(据我追踪,应该是 $form->bind()/$form->submit() 的某个位置),Symfony 和/或 Sonata 实例化了一个 "Wheel" 并尝试持久化它(其中所有的值均为 null)。由于 "Wheel" 具有一些非空约束条件,因此会抛出 DBALException 异常,指出无法插入一个具有 null 值的 "Wheel"。
这很糟糕,我希望能够阻止这种情况发生。如果我没有为 "Wheel" 输入任何详细信息,我不想让虚假的 "Wheel" 危及我的代码和数据库。我期望的是,如果我没有输入任何数据,就不会有任何需要插入/持久化的内容,所以它就被留下来了。但事实并非如此... 有什么想法可以将其变得更加合理吗?
以下是长版本,包含代码块等:
首先是 ORM 定义:
我有两个类,我们简称为 "Car" 和 "Wheel"。 "Car" 可以选择性地与 "Wheel" 建立一对一的关系(这只是一个示例,请跟着走...)。我已经设置了 SonataAdmin,使用 "sonata_type_admin" 将 "WheelAdmin" 内嵌到 "CarAdmin" 中,并尝试创建一辆汽车,而没有输入任何与 "Wheel" 相关的数据。
然而,在提交表单时(据我追踪,应该是 $form->bind()/$form->submit() 的某个位置),Symfony 和/或 Sonata 实例化了一个 "Wheel" 并尝试持久化它(其中所有的值均为 null)。由于 "Wheel" 具有一些非空约束条件,因此会抛出 DBALException 异常,指出无法插入一个具有 null 值的 "Wheel"。
这很糟糕,我希望能够阻止这种情况发生。如果我没有为 "Wheel" 输入任何详细信息,我不想让虚假的 "Wheel" 危及我的代码和数据库。我期望的是,如果我没有输入任何数据,就不会有任何需要插入/持久化的内容,所以它就被留下来了。但事实并非如此... 有什么想法可以将其变得更加合理吗?
以下是长版本,包含代码块等:
首先是 ORM 定义:
# MyNS\MyBundle\Resources\Config\Doctrine\Car.orm.yml
MyNS\MyBundle\Entity\Car:
type: entity
repositoryClass: MyNS\MyBundle\Entity\Repositories\CarRepository
table: test_cars
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
color:
type: string
length: 50
owner:
type: string
length: 50
nullable: true
oneToOne:
leftFrontWheel:
targetEntity: Wheel
cascade: [ persist ]
joinColumn:
name: leftFrontWheelId
referencedColumnName: id
# MyNS\MyBundle\Resources\Config\Doctrine\Wheel.orm.yml
MyNS\MyBundle\Entity\Wheel:
type: entity
repositoryClass: MyNS\MyBundle\Entity\Repositories\WheelRepository
table: test_wheels
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
diameter:
type: integer
length: 5
接下来是 SonataAdmin 类:
namespace MyNS\MyBundle\Admin
use ...
class CarAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('color', null, array('required' => true))
->add('owner', null, array('required' => false))
->add('leftFrontWheel', 'sonata_type_admin', array('delete' => false))
;
}
protected function configureListFields(ListMapper $listMapper) { ... }
}
并且
namespace MyNS\MyBundle\Admin;
use ...
class WheelAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('diameter', null, array('required' => false))
;
}
protected function configureListFields(ListMapper $listMapper) { ... }
}
最后是admin.yml的条目:
services:
sonata.admin.car:
class: MyNS\MyBundle\Admin\CarAdmin
tags:
- { name: sonata.admin, manager_type: orm, label: "Car" }
arguments:
- ~
- MyNS\MyBundle\Entity\Car
- 'SonataAdminBundle:CRUD'
calls:
- [ setTranslationDomain, [MyNS\MyBundle]]
sonata.admin.wheel:
class: MyNS\MyBundle\Admin\WheelAdmin
tags:
- { name: sonata.admin, manager_type: orm, label: "Wheel" }
arguments:
- ~
- MyNS\MyBundle\Entity\Wheel
- 'SonataAdminBundle:CRUD'
calls:
- [ setTranslationDomain, [MyNS\MyBundle]]
期望/必要的行为:
显示一个包含三个字段的表单:
- car.color(必填)
- car.owner(可选)
- car.wheel.diameter(可选)
如果 car.wheel.diameter 留空,则不应创建轮子,并且数据库中的
test_cars.leftFrontWheelId
应保持为null
如果输入了 car.wheel.diameter,则应创建一个轮子并将其链接到汽车上(现有配置似乎可以正常工作)
问题是:如何使系统按照上述方式运行?
$car->setLeftFrontWheel(null)
会清除关系并阻止尝试持久化空轮子。) - caponica