这是在Symfony / Doctrine中嵌套CollectionType的正确方法

时间:2018-12-12 22:31:35

标签: symfony collections doctrine

大家好! 我有3个实体“ Package”,“ ExtraService”和“ ExtraServiceItem”。 包与ExtraService有一个OneToMany关系,而包与ExtraServiceItem有另一个OneToMany关系。

我想知道哪种是在每种“实体类型”表单中进行设置的正确方法。

我已经尝试过这种方式:

实体(仅相关部分):

1-包裹

/**
     * @ORM\OneToMany(targetEntity="App\Entity\ExtraService", mappedBy="package", orphanRemoval=true, cascade={"persist", "remove"})
     * @JMS\MaxDepth(5)
     */
    private $extraServices;

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

/**
     * @return Collection|ExtraService[]
     */
    public function getExtraServices(): Collection
    {
        return $this->extraServices;
    }

    public function addExtraSrevice(ExtraService $item): self
    {
        if (!$this->extraServices->contains($item)) {
            $this->extraServices[] = $item;
            $item->setPackage($this);
        }

        return $this;
    }

    public function removeExtraService(ExtraService $item): self
    {
        if ($this->extraServices->contains($item)) {
            $this->extraServices->removeElement($item);
            // set the owning side to null (unless already changed)
            if ($item->getPackage() === $this) {
                $item->setPackage(null);
            }
        }

        return $this;
    }

2- ExtraService

/**
     * @ORM\ManyToOne(targetEntity="App\Entity\Package", inversedBy="extraServices")
     * @ORM\JoinColumn(nullable=false)
     * @JMS\MaxDepth(3)
     */
    private $package;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\ExtraServiceItem", mappedBy="package", orphanRemoval=true, cascade={"persist", "remove"})
     * @JMS\MaxDepth(3)
     */
    private $extraServiceItems;

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

/**
     * @return Collection|ExtraServiceItem[]
     */
    public function getExtraServiceItems(): Collection
    {
        return $this->extraServiceItems;
    }

    public function addExtraSreviceItem(ExtraServiceItem $item): self
    {
        if (!$this->extraServiceItems->contains($item)) {
            $this->extraServiceItems[] = $item;
            $item->setExtraService($this);
        }

        return $this;
    }

    public function removeExtraServiceItem(ExtraServiceItem $item): self
    {
        if ($this->extraServiceItems->contains($item)) {
            $this->extraServiceItems->removeElement($item);
            // set the owning side to null (unless already changed)
            if ($item->getExtraService() === $this) {
                $item->setExtraService(null);
            }
        }

        return $this;
    }

3- ExtraServiceItem

/**
     * @ORM\ManyToOne(targetEntity="App\Entity\ExtraService", inversedBy="extraServiceItems")
     * @ORM\JoinColumn(nullable=false)
     * @JMS\MaxDepth(3)
     */
    private $extraService;

EntityType(仅相关部分):

1-包裹

class PackageType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ......
            ->add('extraServices', CollectionType::class, [
                'entry_type' => ExtraServiceType::class,
                'allow_add' => true,
                'allow_delete' => true,
            ])
        ;

        $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
            $submittedData = $event->getData();
            $entityData = $event->getForm()->getData();

            $newItems = MergeIndexedById::merge($submittedData['extraServices'], $entityData->getExtraServices());
            $submittedData['extraServices'] = $newItems;

            $event->setData($submittedData);
        });
    }

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

2- ExtraService

class ExtraServiceType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('subtitle')
            ->add('description')
            ->add('package')
            ->add('extraServiceItems', CollectionType::class, [
                'entry_type' => ExtraServiceItemType::class,
                'allow_add' => true,
                'allow_delete' => true,
            ])
        ;

        $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
            $submittedData = $event->getData();
            $entityData = $event->getForm()->getData();

            $newItems = MergeIndexedById::merge($submittedData['extraServiceItems'], $entityData->getExtraServiceItems());
            $submittedData['extraServiceItems'] = $newItems;

            $event->setData($submittedData);
        });
    }

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

3- ExtraServiceItem

class ExtraServiceItemType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('description')
            ->add('recommended')
            ->add('price')
            ->add('periodFrom', null, ['widget' => 'single_text','required' => true])
            ->add('periodTo', null, ['widget' => 'single_text','required' => true])
            ->add('service')
            ->add('extraService')
        ;

    }

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

这是直接创建和编辑ExtraService对象以及相关ExtraServiceItem对象以及Package对象的创建或更新的正确方法吗?

谢谢

0 个答案:

没有答案