ManyToMany 新值必须是数组或 \Traversable 的实例,"NULL" 给定

ManyToMany new value must be an array or an instance of \Traversable, "NULL" given

我的 Symfony 4.2.6 应用程序中有一个 ManyToMany 关系,我希望它可以为 null。

所以我的第一个实体SpecialOffers如下:

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\SpecialOfferRepository")
 */
class SpecialOffer
{
    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Neighbourhood", inversedBy="specialOffers")
     */
     private $neighbourhood;

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

    /**
     * @return Collection|Neighbourhood[]
     */
    public function getNeighbourhood(): Collection
    {
        return $this->neighbourhood;
    }

    public function addNeighbourhood(Neighbourhood $neighbourhood): self
    {
        if (!$this->neighbourhood->contains($neighbourhood)) {
            $this->neighbourhood[] = $neighbourhood;
        }

        return $this;
    }

    public function removeNeighbourhood(Neighbourhood $neighbourhood): self
    {
        if ($this->neighbourhood->contains($neighbourhood)) {
            $this->neighbourhood->removeElement($neighbourhood);
       }

       return $this;
   }
}

与小区有关 class :

/**
 * @ORM\Entity(repositoryClass="App\Repository\NeighbourhoodRepository")
 */
class Neighbourhood implements ResourceInterface
{
    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\SpecialOffer", mappedBy="neighbourhood")
     */
    private $specialOffers;

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

        /**
     * @return Collection|SpecialOffer[]
     */
    public function getSpecialOffers(): Collection
    {
        return $this->specialOffers;
    }

    public function addSpecialOffer(SpecialOffer $specialOffer): self
    {
        if (!$this->specialOffers->contains($specialOffer)) {
            $this->specialOffers[] = $specialOffer;
            $specialOffer->addNeighbourhood($this);
        }

        return $this;
    }

    public function removeSpecialOffer(SpecialOffer $specialOffer): self
    {
         if ($this->specialOffers->contains($specialOffer)) {
            $this->specialOffers->removeElement($specialOffer);
            $specialOffer->removeNeighbourhood($this);
        }

        return $this;
    }
}

最后表格是

class SpecialOfferType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add(
                'neighbourhood',
                EntityType::class,
                [
                    'class' => Neighbourhood::class,
                    'label' => 'form.neighbourhood.label',
                    'translation_domain' => 'Default',
                    'required' => false,
                    'placeholder' => 'form.neighbourhood.all'
                ]
             );
        }
   }

但是当我没有select在我的表单中为特惠提供特定社区时,我收到以下错误: Could not determine access type for property "neighbourhood" in class "App\Entity\SpecialOffer": The property "neighbourhood" in class "App\Entity\SpecialOffer" can be defined with the methods "addNeighbourhood()", "removeNeighbourhood()" but the new value must be an array or an instance of \Traversable, "NULL" given.

无论如何我都可以做到这一点,以便我的特价商品要么包含社区数组,要么只是 null?

我觉得我忽略了一些非常明显的事情,我们将不胜感激

由于您在实体上的字段都是多对多的,因此需要一个数组(或类似的)并且表单字段是 EntityType,这将 return 的一个实体预期类型或 null,我觉得存在某种形式的不对称。

我会考虑使用表单上的 CollectionType from the start or at least setting the multiple 选项到 true,这样 return 值就是一个数组。

另一种选择是向表单字段添加 DataTransformer,这会将 null 变为空数组,将一个实体变为一个实体的数组,反之亦然。

测试 =>

$builder
            ->add(
                'neighbourhood',
                EntityType::class,
                [
                    'class' => Neighbourhood::class,
                    'label' => 'form.neighbourhood.label',
                    'translation_domain' => 'Default',
                    'required' => false,
                    'multiple' => true,
                    'placeholder' => 'form.neighbourhood.all'
                ]
             );