Symfony 形式,一对一关系,一侧可以为空
Symfony form, One-to-one relationship, one side can be null
我有一个 MainConfig
实体,它与 LedConfig
实体具有一对一关系。 LedConfig
可以为空。
<?php
namespace ...
use Doctrine\ORM\Mapping as ORM;
...
/**
* @ORM\Entity
*/
class MainConfig
{
...
/**
* @ORM\OneToOne(targetEntity="...\LedConfig", cascade={"all"})
* @ORM\JoinColumn(name="led_config_id", referencedColumnName="id", nullable=true, unique = true)
*/
private $ledConfig = null;
...
}
<?php
namespace ...
use Doctrine\ORM\Mapping as ORM;
...
/**
* @ORM\Entity
*/
class LedConfig
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="float")
* @Assert\Type(type="float")
*/
private $lowerVoltageThreshold = 11.9;
/**
* @ORM\Column(type="float")
* @Assert\Type(type="float")
*/
private $upperVoltageThreshold = 12.85;
}
<?php
namespace ...;
use Symfony\Component\Form\AbstractType;
...
class MainConfigType extends AbstractType
{
...
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(...)
->add('ledConfig', LedConfigType::class)
...
}
...
}
我在不使用 Symfony 表单的情况下自动将主配置插入数据库。因此,如果我在代码中将 led config 设置为 null - 主配置 table 中的字段 led_config_id
正确设置为 NULL。
但是,当我更新主配置时,我使用的是通过 Symfony 表单处理的 HTTP PUT 请求。
我正在使用 JSON,因此请求正文如下所示:
{..., "ssid":"test","runningMode":"force_on","led_config":null, ...}
处理表单后,MainConfig 实体中的 属性 $ledConfig
神奇地实例化为 LedConfig
对象,所有属性都设置为 NULL ?!
并且数据库更新失败,因为它试图用空字段保存 LedEnttiy。
为什么会这样?
有人可以帮助我并指出我做错了什么吗?
编辑:
我可以在控制器更新操作中破解它,在表单验证之后:
/**
* @Route("...")
* @Method("PUT")
*/
public function updateMainConfigAction($id, Request $request)
{
$requestData = \GuzzleHttp\json_decode($request->getContent(), true);
...
if (!$form->isValid()) {
throw $this->throwApiProblemValidationException($form);
}
if (empty($requestData['led_config'])) {
$mainConfig->setLedConfig(null);
}
$em = $this->getDoctrine()->getManager();
$em->persist($mainConfig);
$em->flush();
...
}
但这有点脏...
Symfony 的 FormType 有 empty_data
和 required
选项。
empty_data
选项具有以下行为:
- 当设置data_class且
required
选项为true
时,则empty_data
是新的$data_class();
- 当设置data_class且
required
选项为false
时,则empty_data
为空;
- 未设置data_class且
compound
选项为true
时,则empty_data
为空数组;
- 当 data_class 未设置且
compound
选项为 false
时,则 empty_data
为空字符串。
required
选项默认为 true
并且 data_class 在 ledConfig 字段上设置,因此当您将其留空时,将设置新的 class给它。如果您希望在未选择任何值时将 ledConfig 字段显式设置为 null
,则可以直接设置 empty_data
选项。
在您的情况下,您需要#2 方案,因此在 ledConfig 字段上将 required
选项设置为 false
并将 empty_data
选项设置为 null
:
...
$builder
->add(...)
->add('ledConfig', LedConfigType::class, array(
'required' => false
'empty_data' => null
))
...
我有一个 MainConfig
实体,它与 LedConfig
实体具有一对一关系。 LedConfig
可以为空。
<?php
namespace ...
use Doctrine\ORM\Mapping as ORM;
...
/**
* @ORM\Entity
*/
class MainConfig
{
...
/**
* @ORM\OneToOne(targetEntity="...\LedConfig", cascade={"all"})
* @ORM\JoinColumn(name="led_config_id", referencedColumnName="id", nullable=true, unique = true)
*/
private $ledConfig = null;
...
}
<?php
namespace ...
use Doctrine\ORM\Mapping as ORM;
...
/**
* @ORM\Entity
*/
class LedConfig
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="float")
* @Assert\Type(type="float")
*/
private $lowerVoltageThreshold = 11.9;
/**
* @ORM\Column(type="float")
* @Assert\Type(type="float")
*/
private $upperVoltageThreshold = 12.85;
}
<?php
namespace ...;
use Symfony\Component\Form\AbstractType;
...
class MainConfigType extends AbstractType
{
...
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(...)
->add('ledConfig', LedConfigType::class)
...
}
...
}
我在不使用 Symfony 表单的情况下自动将主配置插入数据库。因此,如果我在代码中将 led config 设置为 null - 主配置 table 中的字段 led_config_id
正确设置为 NULL。
但是,当我更新主配置时,我使用的是通过 Symfony 表单处理的 HTTP PUT 请求。 我正在使用 JSON,因此请求正文如下所示:
{..., "ssid":"test","runningMode":"force_on","led_config":null, ...}
处理表单后,MainConfig 实体中的 属性 $ledConfig
神奇地实例化为 LedConfig
对象,所有属性都设置为 NULL ?!
并且数据库更新失败,因为它试图用空字段保存 LedEnttiy。
为什么会这样?
有人可以帮助我并指出我做错了什么吗?
编辑: 我可以在控制器更新操作中破解它,在表单验证之后:
/**
* @Route("...")
* @Method("PUT")
*/
public function updateMainConfigAction($id, Request $request)
{
$requestData = \GuzzleHttp\json_decode($request->getContent(), true);
...
if (!$form->isValid()) {
throw $this->throwApiProblemValidationException($form);
}
if (empty($requestData['led_config'])) {
$mainConfig->setLedConfig(null);
}
$em = $this->getDoctrine()->getManager();
$em->persist($mainConfig);
$em->flush();
...
}
但这有点脏...
Symfony 的 FormType 有 empty_data
和 required
选项。
empty_data
选项具有以下行为:
- 当设置data_class且
required
选项为true
时,则empty_data
是新的$data_class(); - 当设置data_class且
required
选项为false
时,则empty_data
为空; - 未设置data_class且
compound
选项为true
时,则empty_data
为空数组; - 当 data_class 未设置且
compound
选项为false
时,则empty_data
为空字符串。
required
选项默认为 true
并且 data_class 在 ledConfig 字段上设置,因此当您将其留空时,将设置新的 class给它。如果您希望在未选择任何值时将 ledConfig 字段显式设置为 null
,则可以直接设置 empty_data
选项。
在您的情况下,您需要#2 方案,因此在 ledConfig 字段上将 required
选项设置为 false
并将 empty_data
选项设置为 null
:
...
$builder
->add(...)
->add('ledConfig', LedConfigType::class, array(
'required' => false
'empty_data' => null
))
...