表单验证嵌套的json对象

时间:2016-11-25 07:55:44

标签: forms rest validation symfony

我有一个Symfony 3.1 REST应用程序,它使用来自客户端的序列化JSON对象,这些对象被反序列化回Symfony中的实体对象。

我遇到的问题是User有一个Status表的外键。当我尝试创建用户时,我必须使用以下格式POST JSON:

{"firstname": "Jane", "lastname": "Doe", "status": "1"}

但是,我想以下面的格式提交JSON。我想采取下面示例中id JSON的status部分插入外键列。发送请求的客户端已经拥有这种格式的对象,并将它们序列化并像这样提交它将非常简单易用。

{"firstname": "Jane", "lastname": "Doe", "status": {"id": 3, "type": "Pending"}

我不知道从哪里开始。我正在考虑数据转换器,但我不完全确定如何让它接受我想要的JSON格式并同时验证它。

NewUserType.php

class NewUserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('firstname')
            ->add('lastname')
            ->add('status')
        ;
    }

DefaultController.php

public function postNewUserAction(Request $Request)
{
    $form = $this->createForm(NewUserType::class, new User());
    $form->submit($Request->request->all());
    ...//validate and persist...
}

user.php的

class User
{
/**
 * @ORM\ManyToOne(targetEntity="Status")
 * @ORM\JoinColumn(name="statusid", referencedColumnName="id")
 */
private $status;

Status.php

class Status
{
    ...
    private $id
    ...   
    private $type;

用户表

mysql> select * from user;
+----+----------+-----------+----------+
| id | statusid | firstname | lastname |
+----+----------+-----------+-----------+
|  1 |        3 | Jane      | Doe      |

状态表

id type
3  Pending

1 个答案:

答案 0 :(得分:1)

您可以使用的一件事是表单事件监听器(https://symfony.com/doc/current/form/events.html

在您的控制器中将JSON请求数据转换为数组:

public function postNewUserAction(Request $Request)
{
    $data = json_decode($Request->getContent(), true);
    $form = $this->createForm(NewUserType::class, new User());
    $form->submit($data);
    if (!$form->isValid()) {...
}

FormType:

class NewUserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
         $builder
            ->add('firstname')
            ->add('lastname')
            ->add('name')
            ->add('status', EntityType::class, array(
                    'class' => 'YourBundle:Status',
                    'choice_label' => 'id',
                ))
        ;

        $builder->addEventListener(
                FormEvents::PRE_SUBMIT,
                array($this, 'onPreSubmitData')
            );
    }

    public function onPreSubmitData(FormEvent $event)
    {
        $eventData = $event->getData();
        $status = $eventData['status'];
        unset($eventData['status']);

        $eventData['status'] = $status['id'];
        $event->setData($eventData);
    }

在onPreSubmitData方法中,您可以根据需要调整请求中的数据:)