我正在使用邮递员来测试我的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',
]
);
答案 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
)可以解决此问题。