无法在类"AppEntityInvoice"中读取属性"member"



我有一个错误,当我使用CollectionType:

https://symfony.com/doc/current/form/form_collections.html

我遵循文档,但我得到以下错误:

无法读取属性"member"在class "AppEntityInvoice"

我的控制器:


#[Route('/subscription/{id}/new-invoice', name: 'new_invoice')]
public function newInvoice(Event $event,Request $request):Response
{
$options['responsibleAdult'] = $this->getUser()->getId();
$options['event'] = $event->getId();
$listEventOption = $this->entityManager->getRepository(EventOption::class)->findBy(['event' => $event->getId()]);
$resultListEventOption = [];
$i=1;
foreach($listEventOption as $value){
$resultListEventOption[$value->getName()] = $i; 
$i++;
}
$options['eventOptions'] = $resultListEventOption;
$invoice = new Invoice();
$form = $this->createForm(InvoiceType::class, $invoice, $options);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$invoice = $form->getData();
//...
}

return $this->render('subscription/new-invoice.html.twig', [
'event' => $event,
'subscriptionId' => $event->getId(),
'form' => $form->createView(),
]);
}

我InvoiceType

:


class InvoiceType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('eventSubscriptions', CollectionType::class, [
'entry_type' => MemberEventSubscriptionType::class,
'label' =>false,
'entry_options' => $options,
'allow_add' => true,
'by_reference' => false,
'allow_delete' => true,
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Invoice::class,
'responsibleAdult' => "",
'event' =>"",
'eventOptions' => []
]);
}
}

我MemberEventSubscriptionType:


class MemberEventSubscriptionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('member', EntityType::class, [
'class' => Member::class,
'label' => false,
'query_builder' => function (MemberRepository $mr) use($options) {
return $mr->findForEventSubscription($options);
},
])
->add('eventRate', EntityType::class, [
'class' => EventRate::class,
'label' => false,
'query_builder' => function (EventRateRepository $evr) {
return $evr->createQueryBuilder('er')
->orderBy('er.amount', 'ASC');
},
])
->add('eventOption', ChoiceType::class, [
'label' => false,
'expanded' => true,
'multiple' => true,
'choices' => $options['eventOptions']
])
->add('submit', SubmitType::class, [
'label' => 'Valider l'inscription',
'attr' => [
'class' => 'btn-block btn-dark'
]
])
;

}

public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => EventSubscription::class,
'csrf_protection' => false,
'responsibleAdult' => "",
'event' =>"",
'eventOptions' => []
]);
}

我的发票:


<?php
namespace AppEntity;
use AppRepositoryInvoiceRepository;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineCommonCollectionsCollection;
use DoctrineORMMapping as ORM;
/**
* @ORMEntity(repositoryClass=InvoiceRepository::class)
*/
class Invoice
{
/**
* @ORMId
* @ORMGeneratedValue
* @ORMColumn(type="integer")
*/
private $id;
/**
* @var Collection|EventSubscription[] 
* @ORMOneToMany(targetEntity=EventSubscription::class, mappedBy="invoice")
* @ORMJoinTable(name="event_subscription_invoice")
*/
protected Collection $eventSubscriptions;
/**
* @ORMColumn(type="boolean")
*/
private $isPaid;
public function __construct()
{
$this->eventSubscriptions = new ArrayCollection();
$this->tugs = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
/** @return EventSubscription[] */
public function getEventSubscriptions(): Collection
{
return $this->eventSubscriptions;
}
public function isIsPaid(): ?bool
{
return $this->isPaid;
}
public function setIsPaid(bool $isPaid): self
{
$this->isPaid = $isPaid;
return $this;
}
public function addEventSubscription(EventSubscription $eventSubscription): void
{
$this->eventSubscriptions->add($eventSubscription);
}
public function removeEventSubscription(EventSubscription $eventSubscription): self
{
if ($this->invoice->contains($eventSubscription)) {
$this->invoice->removeElement($eventSubscription);
}
return $this;
}
}
我EventSubscription

:


<?php
namespace AppEntity;
use AppRepositoryEventSubscriptionRepository;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineCommonCollectionsCollection;
use DoctrineORMMapping as ORM;
use SymfonyComponentValidatorConstraints as Assert;
/**
* @ORMEntity(repositoryClass=EventSubscriptionRepository::class)
*/
class EventSubscription
{
/**
* @ORMId
* @ORMGeneratedValue
* @ORMColumn(type="integer")
*/
private $id;
/**
* @ORMManyToOne(targetEntity=Event::class, inversedBy="eventSubscriptions")
* @ORMJoinColumn(nullable=false)
*/
private Event $event;
/**
* @ORMManyToOne(targetEntity=Member::class, inversedBy="eventSubscriptions")
* @ORMJoinColumn(nullable=false)
*/
private Member $member;
/**
* @ORMManyToOne(targetEntity=User::class, inversedBy="eventSubscriptions")
* @ORMJoinColumn(nullable=false)
*/
private User $user;
/**
* @ORMManyToOne(targetEntity=EventRate::class, inversedBy="eventSubscriptions")
* @ORMJoinColumn(nullable=false)
*/
private EventRate $eventRate;
/**
* @ORMManyToMany(targetEntity=EventOption::class, inversedBy="eventSubscriptions")
* @ORMJoinTable(name="event_subscription_event_option")
*/
private Collection $eventOptions;
/**
* @AssertChoice({"en attente de pièces", "résiliée", "ok"})
* @ORMColumn(type="string", length=255)
*/
private ?string $status;
/**
* @ORMManyToOne(targetEntity=Payment::class, inversedBy="eventSubscriptions", cascade={"persist"})
* @ORMJoinColumn(nullable=false)
*/
private Payment $payment;
/**
* @ORMColumn(type="string", length=255, nullable=true)
* @AssertFile(mimeTypes={"image/gif", "image/jpeg", "image/png", "image/pdf"})
*/
private ?string $medicalCertificateName;
/**
* @ORMColumn(type="string", length=5000, nullable=true)
*/
private ?string $comment;
/**
* @ORMColumn(type="boolean")
*/
private $isPaid = false;
/**
* @ORMManyToOne(targetEntity=Invoice::class, inversedBy="eventSubscriptions", cascade={"persist"})
* @ORMJoinColumn(nullable=false)
*/
private Invoice $invoice;
public function __construct()
{
$this->eventOptions = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getEvent(): Event
{
return $this->event;
}
public function setEvent(Event $event): self
{
$this->event = $event;
return $this;
}
public function getMember(): Member
{
return $this->member;
}
public function setMember(Member $member): self
{
$this->member = $member;
return $this;
}
public function getUser(): User
{
return $this->user;
}
public function setUser(User $user): self
{
$this->user = $user;
return $this;
}
public function getEventRate(): EventRate
{
return $this->eventRate;
}
public function setEventRate(EventRate $eventRate): self
{
$this->eventRate = $eventRate;
return $this;
}
/**
* @return Collection<int, EventOption>
*/
public function getEventOptions(): Collection
{
return $this->eventOptions;
}
public function addEventOption(EventOption $eventOption): self
{
if (!$this->eventOptions->contains($eventOption)) {
$this->eventOptions[] = $eventOption;
}
return $this;
}
public function removeEventOption(EventOption $eventOption): self
{
$this->eventOptions->removeElement($eventOption);
return $this;
}
public function getStatus(): ?string
{
return $this->status;
}
public function setStatus(string $status): self
{
$this->status = $status;
return $this;
}
public function getPayment(): Payment
{
return $this->payment;
}
public function setPayment(Payment $payment): self
{
$this->payment = $payment;
return $this;
}
public function getMedicalCertificateName(): ?string
{
return $this->medicalCertificateName;
}
public function setMedicalCertificateName(string $medicalCertificateName): self
{
$this->medicalCertificateName = $medicalCertificateName;
return $this;
}
/**
* @return string|null
*/
public function getComment(): ?string
{
return $this->comment;
}
/**
* @param string|null $comment
*/
public function setComment(?string $comment): void
{
$this->comment = $comment;
}
public function isIsPaid(): ?bool
{
return $this->isPaid;
}
public function setIsPaid(bool $isPaid): self
{
$this->isPaid = $isPaid;
return $this;
}

public function getInvoice(): Invoice
{
return $this->invoice;
}
public function setInvoice(Invoice $invoice): self
{
$this->invoice = $invoice;
return $this;
}
}

HTML:


<button type="button" class="add_item_link btn btn-dark btn-sm" data-collection-holder-class="eventSubscriptions">Ajouter un membre</button>
{{ form_start(form) }}
<ul class="eventSubscriptions mt-2"
data-index="{{ form.eventSubscriptions|length > 0 ? form.eventSubscriptions|last.vars.name + 1 : 0 }}"
data-prototype="{{ form_widget(form.eventSubscriptions.vars.prototype)|e('html_attr') }}"
></ul>
{{ form_end(form) }}

JS:


const addFormToCollection = (e) => {
const collectionHolder = document.querySelector('.' + e.currentTarget.dataset.collectionHolderClass);
const item = document.createElement('div');
item.innerHTML = collectionHolder
.dataset
.prototype
.replace(
/__name__/g,
collectionHolder.dataset.index
);
collectionHolder.appendChild(item);
collectionHolder.dataset.index++;
};

你有解决办法吗?

错误出现在:

$form = $this->createForm(InvoiceType::class, $invoice, $options);

PS:

映射的false不能工作,因为它会产生其他问题。

我已经测试过了:

$form = $this->createForm(InvoiceType::class, null, $options);

但是当我提交时,我有同样的错误。

所以我找到了解决方案:

我已经改变了我的entry_options在我的InvoiceType:

'entry_options' => [
"responsibleAdult" => $options['responsibleAdult'],
"event" => $options['event'],
"eventOptions" => $options['eventOptions'],
],