Как должна выглядеть форма json с другими вложенными формами - PullRequest
2 голосов
/ 27 июня 2019

Я использую почтальон для проверки моего 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;
    }
}

И классы формы:

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
        ]);
    }
}

CommentType:

<?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"  
}

extraинформация:

Это код контроллера:

$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 Ответ

1 голос
/ 28 июня 2019

Вопреки моему первому предположению, сообщение об ошибке фактически содержит поля , которые были ожидаемы :

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

Однако это сообщение не особенно полезно, когда предоставляются именно эти поля и проблема заключается в коллекции (подформа / подполя).

Однако CollectionType для comments не позволяет добавлять или удалять дочерние элементы (comments), если это не настроено. Добавление allow_add (и, необязательно, allow_delete) устраняет проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...