Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 尝试创建CollectionType调用其他FromType的复选框时出现表单问题(跨实体情况)_Php_Forms_Symfony_Doctrine_Many To Many - Fatal编程技术网

Php 尝试创建CollectionType调用其他FromType的复选框时出现表单问题(跨实体情况)

Php 尝试创建CollectionType调用其他FromType的复选框时出现表单问题(跨实体情况),php,forms,symfony,doctrine,many-to-many,Php,Forms,Symfony,Doctrine,Many To Many,这个案例是一个案例研究,我试图解决这个问题,以便向我的学生解释如何组织实体和创建表单 我的三个实体之间存在这种单一关系: 主角事件注册事件 无法将其转换为多对多关系,因为EventRegistration表中有一些列: 主角: <?php namespace App\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctri

这个案例是一个案例研究,我试图解决这个问题,以便向我的学生解释如何组织实体和创建表单

我的三个实体之间存在这种单一关系:

主角事件注册事件

无法将其转换为多对多关系,因为EventRegistration表中有一些列:

主角:

<?php

namespace App\Entity;

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

/**
 * @ORM\Entity(repositoryClass="App\Repository\ProtagonistRepository")
 */
class Protagonist
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    private $name;

    /**
     * @ORM\Column(type="string", length=100, nullable=true)
     */
    private $japaneseName;

    /**
     * @ORM\Column(type="text")
     */
    private $description;

    /**
     * @ORM\Column(type="string", length=80, nullable=true)
     */
    private $picture;

    /**
     * @ORM\Column(type="string", length=80, nullable=true)
     */
    private $background;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    private $updated_at;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Category", inversedBy="protagonists")
     * @ORM\JoinColumn(nullable=false)
     */
    private $category;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Tag", mappedBy="protagonists")
     */
    private $tags;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Registration", mappedBy="protagonist")
     */
    private $registrations;

    /**
     * @ORM\Column(type="boolean", nullable=true)
     */
    private $isAlive;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Event", mappedBy="protagonists")
     */
    private $events;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\EventRegistration", mappedBy="protagonist")
     */
    private $eventRegistrations;

    public function __construct()
    {
        $this->tags = new ArrayCollection();
        $this->registrations = new ArrayCollection();
        $this->events = new ArrayCollection();
        $this->eventRegistrations = new ArrayCollection();
    }

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

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getJapaneseName(): ?string
    {
        return $this->japaneseName;
    }

    public function setJapaneseName(?string $japaneseName): self
    {
        $this->japaneseName = $japaneseName;

        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(string $description): self
    {
        $this->description = $description;

        return $this;
    }

    public function getPicture(): ?string
    {
        return $this->picture;
    }

    public function setPicture(?string $picture): self
    {
        $this->picture = $picture;

        return $this;
    }

    public function getBackground(): ?string
    {
        return $this->background;
    }

    public function setBackground(?string $background): self
    {
        $this->background = $background;

        return $this;
    }

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

    public function setUpdatedAt(?\DateTimeInterface $updated_at): self
    {
        $this->updated_at = $updated_at;

        return $this;
    }

    public function getCategory(): ?Category
    {
        return $this->category;
    }

    public function setCategory(?Category $category): self
    {
        $this->category = $category;

        return $this;
    }

    /**
     * @return Collection|Tag[]
     */
    public function getTags(): Collection
    {
        return $this->tags;
    }

    public function addTag(Tag $tag): self
    {
        if (!$this->tags->contains($tag)) {
            $this->tags[] = $tag;
            $tag->addProtagonist($this);
        }

        return $this;
    }

    public function removeTag(Tag $tag): self
    {
        if ($this->tags->contains($tag)) {
            $this->tags->removeElement($tag);
            $tag->removeProtagonist($this);
        }

        return $this;
    }

    /**
     * @return Collection|Registration[]
     */
    public function getRegistrations(): Collection
    {
        return $this->registrations;
    }

    public function addRegistration(Registration $registration): self
    {
        if (!$this->registrations->contains($registration)) {
            $this->registrations[] = $registration;
            $registration->setProtagonist($this);
        }

        return $this;
    }

    public function removeRegistration(Registration $registration): self
    {
        if ($this->registrations->contains($registration)) {
            $this->registrations->removeElement($registration);
            // set the owning side to null (unless already changed)
            if ($registration->getProtagonist() === $this) {
                $registration->setProtagonist(null);
            }
        }

        return $this;
    }

    public function getIsAlive(): ?bool
    {
        return $this->isAlive;
    }

    public function setIsAlive(?bool $isAlive): self
    {
        $this->isAlive = $isAlive;

        return $this;
    }

    /**
     * @return Collection|Event[]
     */
    public function getEvents(): Collection
    {
        return $this->events;
    }

    public function addEvent(Event $event): self
    {
        if (!$this->events->contains($event)) {
            $this->events[] = $event;
            $event->addProtagonist($this);
        }

        return $this;
    }

    public function removeEvent(Event $event): self
    {
        if ($this->events->contains($event)) {
            $this->events->removeElement($event);
            $event->removeProtagonist($this);
        }

        return $this;
    }

    /**
     * @return Collection|EventRegistration[]
     */
    public function getEventRegistrations(): Collection
    {
        return $this->eventRegistrations;
    }

    public function addEventRegistration(EventRegistration $eventRegistration): self
    {
        if (!$this->eventRegistrations->contains($eventRegistration)) {
            $this->eventRegistrations[] = $eventRegistration;
            $eventRegistration->setProtagonist($this);
        }

        return $this;
    }

    public function removeEventRegistration(EventRegistration $eventRegistration): self
    {
        if ($this->eventRegistrations->contains($eventRegistration)) {
            $this->eventRegistrations->removeElement($eventRegistration);
            // set the owning side to null (unless already changed)
            if ($eventRegistration->getProtagonist() === $this) {
                $eventRegistration->setProtagonist(null);
            }
        }

        return $this;
    }

}
一些理论 实体是具有身份、数据和行为的模型、业务对象

他们是你商业模式的核心和基石

当我们设计实体时,首先我们应该将它们视为对象,它们具有它们自己的形状和职责,而不是它们仅仅是存储在数据库中的数据的容器。此外,我们还应该关心实体之间的适当关系

理想情况下,实体应始终有效。如果是这样,它们可以在任何时候被持久化


持久性是一个单独的问题

在一般情况下,甚至不需要将实体持久化到数据库中。它们可以保存在内存、文件系统、键值存储等中


表单也是一个单独的关注点,更接近于使用用户界面

表单帮助我们呈现用户界面,将来自用户的请求转换为一些已知形状的结构,这些结构比来自请求的原始数据更易于使用,并验证提交的数据

这些结构只是从请求中检索数据的容器,它们不应该有任何行为

这些结构在某些时候可能无效

所描述的问题是什么? 所以,让实体在数据结构下扮演这些表单的角色可能不是最好的主意

这显然是不同层之间的关注点和刚性耦合的混合

这就是为什么你会有这些问题

<> >而不是使用<代码>事件注册< /代码>类作为<代码> DATAAL类 <代码>事件注册类型< /代码>和<代码>主角< /代码> -<代码> PrimististType < /代码> -考虑创建单独的数据结构。仅当已成功验证提交的数据时,才将其传播到实体


一些有用的链接可以阅读更多关于该主题的内容(尽管作者称之为底层结构-命令somewhy):

其他有用的主题:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\EventRegistrationRepository")
 */
class EventRegistration
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="datetimetz")
     */
    private $registrationDate;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Protagonist", inversedBy="eventRegistrations")
     */
    private $protagonist;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Event", inversedBy="eventRegistrations")
     */
    private $event;

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

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

    public function setRegistrationDate(\DateTimeInterface $registrationDate): self
    {
        $this->registrationDate = $registrationDate;

        return $this;
    }

    public function getProtagonist(): ?Protagonist
    {
        return $this->protagonist;
    }

    public function setProtagonist(?Protagonist $protagonist): self
    {
        $this->protagonist = $protagonist;

        return $this;
    }

    public function getEvent(): ?Event
    {
        return $this->event;
    }

    public function setEvent(?Event $event): self
    {
        $this->event = $event;

        return $this;
    }
}
<?php

namespace App\Entity;

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

/**
 * @ORM\Entity(repositoryClass="App\Repository\EventRepository")
 */
class Event
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    private $name;

    /**
     * @ORM\Column(type="datetimetz", nullable=true)
     */
    private $start_date;

    /**
     * @ORM\Column(type="datetimetz", nullable=true)
     */
    private $end_date;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Protagonist", inversedBy="events")
     */
    private $protagonists;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\EventRegistration", mappedBy="event")
     */
    private $eventRegistrations;

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

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

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

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

    public function setStartDate(?\DateTimeInterface $start_date): self
    {
        $this->start_date = $start_date;

        return $this;
    }

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

    public function setEndDate(?\DateTimeInterface $end_date): self
    {
        $this->end_date = $end_date;

        return $this;
    }

    /**
     * @return Collection|Protagonist[]
     */
    public function getProtagonists(): Collection
    {
        return $this->protagonists;
    }

    public function addProtagonist(Protagonist $protagonist): self
    {
        if (!$this->protagonists->contains($protagonist)) {
            $this->protagonists[] = $protagonist;
        }

        return $this;
    }

    public function removeProtagonist(Protagonist $protagonist): self
    {
        if ($this->protagonists->contains($protagonist)) {
            $this->protagonists->removeElement($protagonist);
        }

        return $this;
    }

    /**
     * @return Collection|EventRegistration[]
     */
    public function getEventRegistrations(): Collection
    {
        return $this->eventRegistrations;
    }

    public function addEventRegistration(EventRegistration $eventRegistration): self
    {
        if (!$this->eventRegistrations->contains($eventRegistration)) {
            $this->eventRegistrations[] = $eventRegistration;
            $eventRegistration->setEvent($this);
        }

        return $this;
    }

    public function removeEventRegistration(EventRegistration $eventRegistration): self
    {
        if ($this->eventRegistrations->contains($eventRegistration)) {
            $this->eventRegistrations->removeElement($eventRegistration);
            // set the owning side to null (unless already changed)
            if ($eventRegistration->getEvent() === $this) {
                $eventRegistration->setEvent(null);
            }
        }

        return $this;
    }
}
<?php

namespace App\Form;

use App\Entity\Category;
use App\Entity\Event;
use App\Entity\EventRegistration;
use App\Entity\Protagonist;
use App\Entity\Tag;
use App\Repository\EventRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
 * Class ProtagonistType
 * @package App\Form
 */
class ProtagonistType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', TextType::class)
            ->add('japaneseName', TextType::class, [
                'required' => false
            ])
            ->add('description', TextareaType::class)
            ->add('picture', TextType::class, [
                'required' => false
            ])
            ->add('background', TextType::class, [
                'required' => false
            ])
            ->add('isAlive', CheckboxType::class)
             ->add('category', EntityType::class, [
                'class' => Category::class,
                'choice_label' => 'title',
                'expanded' => true,
                 'multiple' => false
            ])
            ->add('tags', EntityType::class, [
                'class' => Tag::class,
                'choice_label' => 'name',
                'expanded' => true,
                'multiple' => true,
                'by_reference' => false,
            ])
            **->add('eventRegistrations', CollectionType::class, [
                'entry_type' => EventRegistrationType::class
            ])**
        ;
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Protagonist::class,
        ]);
    }
}
<?php

namespace App\Form;

use App\Entity\Event;
use App\Entity\EventRegistration;
use App\Repository\EventRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
 * Class EventRegistrationType
 * @package App\Form
 */
class EventRegistrationType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('event', EntityType::class, [
                'class' => Event::class,
                'choice_label' => 'name',
                'multiple' => true,
                'expanded' => true,
                'by_reference' => false,
            ])
        ;
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => EventRegistration::class,
        ]);
    }
}