应该如何看起来像嵌入了其他表单的json表单

时间:2019-06-27 02:32:00

标签: json forms symfony

我正在使用邮递员来测试我的json-api。我必须去相关实体:

出版物:

<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity(repositoryClass="App\Repository\PublicationRepository")
 */
class Publication
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @Assert\NotBlank
     * @ORM\Column(type="string", length=100)
     */
    private $title;

    /**
     * @Assert\NotBlank
     * @ORM\Column(type="string", length=500)
     */
    private $body;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="publication", orphanRemoval=true)
     */
    private $comments;

    public function __construct()
    {
        $this->comments = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getTitle(): ?string
    {
        return $this->title;
    }

    public function setTitle(string $title): self
    {
        $this->title = $title;

        return $this;
    }

    public function getBody(): ?string
    {
        return $this->body;
    }

    public function setBody(string $body): self
    {
        $this->body = $body;
        return $this;
    }

    /**
     * @return Collection|Comment[]
     */
    public function getComments(): Collection
    {
        return $this->comments;
    }

    public function addComment(Comment $comment): self
    {
        if (!$this->comments->contains($comment)) {
            $this->comments[] = $comment;
            $comment->setPublication($this);
        }

        return $this;
    }

    public function removeComment(Comment $comment): self
    {
        if ($this->comments->contains($comment)) {
            $this->comments->removeElement($comment);
            // set the owning side to null (unless already changed)
            if ($comment->getPublication() === $this) {
                $comment->setPublication(null);
            }
        }
        return $this;
    }
}

评论:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity(repositoryClass="App\Repository\CommentRepository")
 *
 */
class Comment
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @Assert\NotBlank
     * @ORM\Column(type="string", length=255)
     */
    private $body;

    /**
     * @Assert\Positive
     * @ORM\Column(type="integer")
     */
    private $likeCount;

    /**
     * @return mixed
     */
    public function getLikeCount()
    {
        return $this->likeCount;
    }

    /**
     * @param mixed $likeCount
     */
    public function setLikeCount($likeCount): void
    {
        $this->likeCount = $likeCount;
    }

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Publication", inversedBy="comments")
     * @ORM\JoinColumn(nullable=false)
     */
    private $publication;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getBody(): ?string
    {
        return $this->body;
    }

    public function setBody(string $body): self
    {
        $this->body = $body;

        return $this;
    }

    public function getPublication(): ?Publication
    {
        return $this->publication;
    }

    public function setPublication(?Publication $publication): self
    {
        $this->publication = $publication;

        return $this;
    }
}

以及Form类:

PublicationType:

<?php

namespace App\Form;

use App\Entity\Publication;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class PublicationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('body')
            ->add('comments', CollectionType::class, [
                'entry_type' => CommentType::class,
                'entry_options' => ['label' => false],
            ]);
        ;
    }

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

评论类型:

<?php

namespace App\Form;


use App\Entity\Comment;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CommentType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('body')
            ->add('publication')
            ->add('likeCount');
    }

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

据此:https://symfony.com/doc/current/form/form_collections.html发布表单能够收到嵌入的评论表单:

我在邮递员POST请求中尝试了类似的操作:

{
    "title":"post with comments",
    "body":"some text",
    "comments":[
        {"body":"comment1","likeCount":"5"},
        {"body":"comment2","likeCount":"8"}
        ]
}

但是我明白了:

{ "code": 400, "message": "Validation Failed", "errors": { "errors": [ "This form should not contain extra fields." ], "children": { "title": {}, "body": {}, "comments": {} } } }

问题是:

JSON请求的外观如何?

编辑:

我认为麻烦不在于根键,这是因为在设置用于提交表单的ManyToOne关系之前,是这样的:

{
    "title":"post with comments",
    "body":"some text"  
}

其他信息:

这是控制器代码:

$form = $this->formFactory->create(PublicationType::class, new Publication());
        $form->submit($request->request->all());
        if (false === $form->isValid()) {
            return $this->viewhandler->createResponse($this->view($form),$request,'json');
        }
        $this->entityManager->persist($form->getData());
        $this->entityManager->flush();
        return new JsonResponse(
            [
                'status' => 'ok',
            ]
        );

1 个答案:

答案 0 :(得分:1)

与我的第一个假设相反,错误消息实际上确实提供了预期的字段

{ 
    "code": 400, 
    "message": "Validation Failed", 
    "errors": { 
        "errors": [  
            "This form should not contain extra fields." 
        ], 
        "children": { 
            "title": {}, 
            "body": {}, 
            "comments": {} 
        } 
    } 
}

但是,当确切提供了这些字段并且问题出在集合(子表单/子字段)中时,该消息并不是特别有用。

CollectionType的{​​{1}}不允许添加或删除子级(comments),除非进行配置。添加allow_add(和可选的comments)可以解决此问题。