【问题标题】:Symfony 4 JSON nested entities through formSymfony 4 JSON 通过表单嵌套实体
【发布时间】:2018-10-28 19:25:10
【问题描述】:

我正在尝试通过复杂的表单提交 JSON。我无法弄清楚我错过了什么。 “正常”形式正在发挥作用。我可以通过组获取序列化数据。

班级任务板

    class TaskBoard
{
    /**
     * @var integer $id id
     * 
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @var \DateTime $createdTime createdTime
     * 
     * @ORM\Column(type="datetime")
     * @Assert\DateTime()
     */
    private $createdTime;

    /**
     * @var \DateTime $lastUpdatedTime lastUpdatedTime
     * 
     * @ORM\Column(type="datetime", nullable=true)
     * @Assert\DateTime()
     */
    private $lastUpdatedTime;

    /**
     * @var string $name name
     * 
     * @ORM\Column(type="string", length=20)
     * @Assert\Type("string")
     * @Assert\NotBlank()
     * @Assert\Length(
     *      min = 2,
     *      max = 20,
     *      minMessage = "The name must be at least {{ limit }} characters long",
     *      maxMessage = "The name cannot be longer than {{ limit }} characters"
     * )
     */
    private $name;

    /**
     * @var App\Entity\User $user user
     * 
     * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="taskboards", cascade={"persist"})
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
    private $user;

    /**
     * @var string $description description
     * 
     * @ORM\Column(type="text", nullable=true)
     * @Assert\Type("string")
     */
    private $description;

    /**
     * @var App\Entity\Status $status status
     * 
     * @ORM\ManyToOne(targetEntity="App\Entity\Status", inversedBy="taskboards", cascade={"persist"})
     * @ORM\JoinColumn(name="status_id", referencedColumnName="id", nullable=false)
     */
    private $status;

    /**
     * @var boolean $completed completed
     * 
     * @ORM\Column(type="boolean")
     */
    private $completed;

    /**
     * @var \DateTime $deadLine deadLine
     * 
     * @ORM\Column(type="date", nullable=true)
     * @Assert\DateTime()
     * @Assert\GreaterThanOrEqual("today")
     */
    private $deadLine;

班级状态

class Status
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=20)
     */
    private $name;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\TaskBoard", mappedBy="status", cascade={"persist"})
     */
    public $taskboards;

班级用户

class User extends BaseUser
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    protected $id;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\TaskBoard", mappedBy="user", cascade={"persist"})
     */
    public $taskboards;

表格

class TaskBoardType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
                ->add('name', TextType::class)
                ->add('user', EntityType::class, array(
                    'class' => User::class,
                    'choice_label' => 'username',
                        )
                )
                ->add('description', TextareaType::class, array(
                    'required' => false
                ))
                ->add('status', EntityType::class, array(
                    'class' => Status::class,
                    'choice_label' => 'name',
                        )
                )
                ->add('deadLine', DateTimeType::class)
        ;
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults([
            'data_class' => TaskBoard::class,
            'csrf_protection' => false,
        ]);
    }

控制器

class TaskBoardAPIController extends AbstractController {

    public function postTaskBoard(Request $request) {

        $form = $this->createForm(TaskBoardType::class, new TaskBoard());

        $data = json_decode(
                $request->getContent(), true
        );

        var_dump($data);

        $form->submit($data);

        if (!$form->isValid()) {
            return new JsonResponse(
                    [
                'status' => 'error',
                'errors' => $form->getErrors(),
                'form' => $form,
                    ], JsonResponse::HTTP_BAD_REQUEST
            );
        }

        $this->entityManager->persist($form->getData());
        $this->entityManager->flush();

        return new JsonResponse(
                [
            'status' => 'ok',
                ], JsonResponse::HTTP_CREATED
        );
    }

JSON 发送

{
    "name": "XXX",
    "user": {
        "id": 1,
        "username": "BFA"
    },
    "description": "XXXXXXXXXXXXXXX",
    "status": {
        "id": 1,
        "name": "To Do"
    },
    "completed": false
}

JsonResponse 中的表单无效且为空白。

我基于:https://codereviewvideos.com/course/beginners-guide-back-end-json-api-front-end-2018/video/symfony-4-json-api-form-submissionDeserialize an entity with a relationship with Symfony Serializer Component

感谢您的帮助。

【问题讨论】:

    标签: php json forms symfony4


    【解决方案1】:

    错误是 JSON 输入。

    表格是这样做的:

    class TaskBoardType extends AbstractType {
    
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
                ->add('name', TextType::class)
                ->add('user', EntityType::class, array(
                    'class' => User::class,
                    'choice_label' => 'username',
                        )
                )
                ->add('description', TextareaType::class, array(
                    'required' => false
                ))
                ->add('status', EntityType::class, array(
                    'class' => Status::class,
                    'choice_label' => 'name',
                        )
                )
                ->add('deadLine', DateTimeType::class)
        ;
    }
    
    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults([
            'data_class' => TaskBoard::class,
            'csrf_protection' => false,
        ]);
    }
    

    检查表单生成的代码时,结果如下:

    <div>
       <label for="task_board_user" class="required">User</label>
       <select id="task_board_user" name="task_board[user]">
          <option value="1">XXX</option>
          <option value="2">XXX</option>
       </select>
    </div>
    

    因此该表单直接期望一个 INT/ID。

    通过按如下方式更改 JSON,它会通过验证:

    {
        "name": "XXXO",
        "user": 1,
        "description": "XXXXXXXXXXXXXXX",
        "status": 1
    }
    

    【讨论】:

      【解决方案2】:

      您忘记处理和获取表单提交。 请注意,您将需要使用类似的方式获取请求数据

          $form = $this->createFormBuilder($task)
              ... add fields
              ->getForm();
      
          $form->handleRequest($request); // handling request
      
          if ($form->isSubmitted() && $form->isValid()) {
              // $form->getData() holds the submitted values
              // but, the original `$task` variable has also been updated
              $task = $form->getData();
      
              // ... perform some action, such as saving the task to the database
              // for example, if Task is a Doctrine entity, save it!
              // $entityManager = $this->getDoctrine()->getManager();
              // $entityManager->persist($task);
              // $entityManager->flush();
      
              return $this->redirectToRoute('...');
          }
      

      更多信息,请参阅Handling Form Submissions

      【讨论】:

        猜你喜欢
        • 2019-07-07
        • 2017-09-24
        • 1970-01-01
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        • 2021-11-08
        • 1970-01-01
        • 2015-11-01
        相关资源
        最近更新 更多