首页 > 解决方案 > 对多关系的意外不可迭代值

问题描述

当我运行 phpunit 时,

$this->assertResponseIsSuccessful();

显示错误:

'hydra:description' => 'Unexpected non-iterable value for to-many relation'

Failed asserting that the Response is successful.
HTTP/1.1 400 Bad Request
Cache-Control:          no-cache, private
Content-Type:           application/ld+json; charset=utf-8
Date:                   Fri, 09 Jul 2021 13:06:48 GMT
Link:                   <http://example.com/docs.jsonld>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"
X-Content-Type-Options: nosniff
X-Frame-Options:        deny
X-Robots-Tag:           noindex

我认为这个问题与实体中的空值有关。

    /**
     * @return Collection|null<int, Falta>
     */
    public function getFalta(): ?Collection
    {
        return $this->falta;
    }

这说得通?以及如何解决这个问题?

我的完整实体:

<?php

declare(strict_types=1);

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 * @ORM\Table(schema="db_automacao_sti", name="tb_pessoa")
 *
 * @ApiResource(
 *     normalizationContext={"groups"={"pessoa:read"}},
 *     denormalizationContext={"groups"={"pessoa:write"}},
 *     collectionOperations={
 *         "get"
 *     },
 *     itemOperations={
 *         "get"
 *     }
 * )
 * @ApiFilter(SearchFilter::class, properties={"ordemServicoContratoItemPessoa.itemContrato.contrato": "exact","ordemServicoContratoItemPessoa.itemContrato": "exact"})
 */
class Pessoa
{
    /**
     * @Groups({"pessoa:read"})
     *
     * @ORM\Id
     * @ORM\Column(name="pk_pessoa", type="integer")
     * @ORM\GeneratedValue(strategy="SEQUENCE")
     * @ORM\SequenceGenerator(sequenceName="sq_pessoa", initialValue=1, allocationSize=100)
     */
    private ?int $id = null;

    /**
     * @Groups({"pessoa:read"})
     *
     * @ORM\Column(name="dh_criado_em", type="datetime")
     */
    private ?\DateTimeInterface $criadoEm = null;

    /**
     * @Groups({"pessoa:read"})
     *
     * @ORM\Column(name="dh_atualizado_em", type="datetime")
     */
    private ?\DateTimeInterface $atualizadoEm = null;

    /**
     * @Assert\NotBlank
     * @Assert\Type("\DateTimeInterface")
     *
     * @Groups({"pessoa:read", "pessoa:write"})
     *
     * @ORM\Column(name="dh_contratado_em", type="datetime")
     */
    private ?\DateTimeInterface $contratadoEm = null;

    /**
     * @Assert\NotBlank
     * @Assert\Length(max=255)
     *
     * @Groups({"pessoa:read", "pessoa:write"})
     *
     * @ORM\Column(name="no_pessoa", type="string", length=255)
     */
    private ?string $nome = null;

    /**
     * @Assert\NotBlank
     * @Assert\Length(11)
     *
     * @Groups({"pessoa:read", "pessoa:write"})
     *
     * @ORM\Column(name="nu_cpf", type="string", length=11)
     */
    private ?string $cpf = null;

    /**
     * @Assert\NotBlank
     * @Assert\Length(max=255)
     * @Assert\Email
     *
     * @Groups({"pessoa:read", "pessoa:write"})
     *
     * @ORM\Column(name="ds_email", type="string", length=255)
     */
    private ?string $email = null;

    /**
     * @Assert\NotBlank
     * @Assert\Length(min=10, max=11)
     * @Assert\Type("digit")
     *
     * @Groups({"pessoa:read", "pessoa:write"})
     *
     * @ORM\Column(name="nu_telefone", type="string", length=11)
     */
    private ?string $numeroTelefone = null;

    /**
     * @var Collection<int, OrdemServicoContratoItemPessoa> Coleção de ordemServicoContratoItemPessoa
     * @ORM\OneToMany(targetEntity="OrdemServicoContratoItemPessoa", mappedBy="pessoa")
     */
    private $ordemServicoContratoItemPessoa;

    /**
     * @var Collection<int, Falta> Coleção de falta
     * @ORM\OneToMany(targetEntity="Falta", mappedBy="pessoa")
     * @Groups({"item:read"})
     */
    private $falta;

    /**
     * @ORM\PrePersist
     * @ORM\PreUpdate
     */
    public function onPrePersistOrUpdate(): void
    {
        $this->setAtualizadoEm(new \DateTimeImmutable('now', new \DateTimeZone('UTC')));

        if (null === $this->getCriadoEm()) {
            $this->setCriadoEm(new \DateTimeImmutable('now', new \DateTimeZone('UTC')));
        }
    }

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

    public function getCriadoEm(): ?\DateTimeInterface
    {
        return $this->criadoEm;
    }

    public function setCriadoEm(\DateTimeInterface $criadoEm): self
    {
        $this->criadoEm = $criadoEm;

        return $this;
    }

    public function getAtualizadoEm(): ?\DateTimeInterface
    {
        return $this->atualizadoEm;
    }

    public function setAtualizadoEm(\DateTimeInterface $atualizadoEm): self
    {
        $this->atualizadoEm = $atualizadoEm;

        return $this;
    }

    public function getContratadoEm(): ?\DateTimeInterface
    {
        return $this->contratadoEm;
    }

    public function setContratadoEm(\DateTimeInterface $contratadoEm): self
    {
        $this->contratadoEm = $contratadoEm;

        return $this;
    }

    public function getNome(): ?string
    {
        return $this->nome;
    }

    public function setNome(string $nome): self
    {
        $this->nome = $nome;

        return $this;
    }

    public function getCpf(): ?string
    {
        return $this->cpf;
    }

    public function setCpf(string $cpf): self
    {
        $this->cpf = $cpf;

        return $this;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    public function getNumeroTelefone(): ?string
    {
        return $this->numeroTelefone;
    }

    public function setNumeroTelefone(string $numeroTelefone): self
    {
        $this->numeroTelefone = $numeroTelefone;

        return $this;
    }

    /**
     * @return Collection<int, OrdemServicoContratoItemPessoa>
     */
    public function getOrdemServicoContratoItemPessoa(): Collection
    {
        return $this->ordemServicoContratoItemPessoa;
    }

    /**
     * @return Collection|null<int, Falta>
     */
    public function getFalta(): ?Collection
    {
        return $this->falta;
    }
}

标签: unit-testingsymfonyphpunit

解决方案


您遇到错误,因为Collection(ArrayCollection) 未初始化。

将构造函数添加到您的实体并将每个集合值设置为new ArrayCollection();

它应该看起来像:

use Doctrine\Common\Collections\ArrayCollection;

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

推荐阅读