2016-05-09 11 views
0

Ich versuche, ein Formular zu generieren, das ich denke braucht nur zwei Einheiten. Der einzige Weg, wie ich es geschafft habe, ist die Verwendung von drei. Das Formular, das ich habe funktioniert, aber es ist sehr langsam, da es viele Datensätze in der Datenbank für jede Entität gibt. Gibt es einen klügeren Weg, wie ich damit umgehen sollte?Symfony-Formulare mit einem Array anstelle von Entity generieren?

Was ich versuche zu erreichen, ist ein verschachtelt InvoiceType Formular für jede Kunde Einheit in der Datenbank. Der Admin-Benutzer sollte dann in der Lage sein, die Kunden, für die er einen Rechnungs-Stapel erstellen möchte, anzukreuzen. Es sollte wie folgt aussehen:

| Generate Invoice? | Customer | Amount | Date  | Notes  | 
|-------------------|------------|----------|------------|-----------| 
| ☑    | Customer1 | 100.00 | 2016-05-08 |-----------| 
| ☐    | Customer2 | 105.55 | 2016-05-09 |-----------| 

Derzeit habe ich es durch Verwendung von drei Einheiten arbeiten. Ich habe eine Invoicebatch Entität erstellt, um zu identifizieren, welche Charge (falls vorhanden) eine Rechnung gehört. Aber, wie ich ein neues Rechnungs Objekt für jeden Kunden in der Datenbank erstellen müssen, ich bin Laden (glaube ich) jedes Customer-Objekt in das Formular ein Objekt in meinem Controller:

public function batchInvoicesAction(Request $request) 
{ 
    $em = $this->getDoctrine()->getManager(); 
    $customers = $em->getRepository('AppBundle:Customer')->findAll(); 
    $batch = new InvoiceBatch(); 
    foreach ($customers as $customer) { 
     $invoice = new Invoice(); 
     $invoice->setCustomerId($customer); 
     $invoice->setSelected(True); 
     $invoice->setCreatedate(new \Datetime()); 
     $invoice->setAmount($customer->getDefaultinvoiceamount()); 
     $invoice->setinvoicebatchid($batch); 
     $batch->addInvoiceId($invoice); 
    } 
    $form = $this->createForm(InvoiceBatchType::class, $batch); 
    $form->handleRequest($request); 

    if ($form->isSubmitted() && ($form->isValid())) { 
     $batchform = $form->getData(); 
     foreach ($batchform->getInvoiceids() as $invoiceform) { 
      if ($invoiceform->getSelected() == False) { 
       $batchform->removeInvoiceId($invoiceform); 
      } else { 
       $em->persist($invoiceform); 
      } 
     } 
     $em->persist($batchform); 
     $em->flush(); 
     return $this->redirectToRoute('view_monthly_invoices'); 
    } 
    return $this->render('invoices/new.batch.invoice.html.twig') 
} 

Mein InvoiceBatchType ist als unten :

class InvoiceBatchType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('batchevent', TextType::class, array(
      )) 
      ->add('invoice_ids', CollectionType::class, array(
       'entry_type' => InvoiceForBulkType::class, 
      )) 
     ; 
    } 

Mein InvoiceForBulkType ist:

class InvoiceForBulkType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('selected', CheckboxType::class, array(
       'label' => ' ', 
       'required' => false, 
      )) 
      ->add('customer_id', EntityType::class, array(
        'class' => 'AppBundle:Customer', 
        'choice_label' => 'FullName', 
        'label'=>'Customer', 
        'disabled'=>true, 
       ) 
      ) 
      ->add('amount', TextType::class, array(
       'label' => 'Amount', 
      )) 

      ->add('invoicedate', DateType::class, array(
       'widget' => 'single_text', 
       'data' => new \DateTime('now'), 
       'format' => 'dd/MMM/yyyy', 
       'label' => 'Date of invoice', 
       'attr'=> array(
        'class'=>'datepicker', 
       ) 
      )) 

      ->add('description', TextType::class, array(
       'required'=>false, 
      )) 
     ; 
    } 
} 

ich es dachte, möglich sein kann, die Kundennamen zu laden einfach als ein Array, da ich nur einen Kundennamen in jeder Zeile anzeigen möchte (dh kein Dropdown oder anderes Formularelement). Ich habe versucht, ein paar Versuche, aber ohne Glück, so denke ich, dass die $customer Objekte für Hintergrundprozesse in Symfony enthalten sein müssen, die ich nicht kenne (Ich habe eine Rechnung).

+0

starten durch Entfernen des "Ich denke," Teil des Problems. Überprüfen Sie die Web Debug-Symbolleiste, um festzustellen, welche Abfragen tatsächlich ausgeführt werden. – Cerad

+0

Guten Punkt danke @Cerad - Lehre = 7ms (90MB), Controller = 37,325ms (937MB), Zweig Dateien = 20,806ms (937MB), Kernel-Antwort = 79ms (937MB) – Bendy

+0

Und di bestätigen, dass Tausende von Abfragen durchgeführt werden ? – Cerad

Antwort

1

Ich schaffte es am Ende zu arbeiten - das Problem war, dass mir die Optionen zum Übergeben von Entitäten in Symfony-Form nicht bekannt waren. Ich habe versucht, die Theorie/Logik unten in der Hoffnung zusammenfassen es von Hilfe ist zu jeder andere kämpfen, um ihre Köpfe um Symfony Formen zu bekommen:

durch die Symfony Form documentation gelesen hatte dachte ich fälschlicherweise, dass nur EntityType und CollectionType umgehen konnte ein Empfang Entität als Eingabe. Daher verursachte mein InvoiceForBatchType das Problem - es wurde ALLE Kunden in jede einzelne Rechnung geladen.

Das Schlüsselkonzept I für Symfony Formen gefehlt hatte ist:

Wenn Sie ein Unternehmen unterwegs sind, die Sie zugreifen können, wollen, dann Sie nicht Verwendung EntityType (es sei denn, Sie wollen Popup Dropdown/Radio/Ticks). Stattdessen erstellen Sie eine neue Datei eine verschachtelte Formtype

Das war dann eine einfache Lösung in meinem Fall zu definieren, indem:

1.Aktualisieren InvoiceForBulkType zu:
class InvoiceForBulkType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      /* ... */ 

      ->add('customer_id', CustomerForInvoiceType::class) 

      /* ... */ 
     ; 
    } 
} 
2. Erstellen CustomerForInvoiceType:
class CustomerForInvoice extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('fullname', TextType::class, array(
      )) 
     ; 
    } 

    /* ... */ 
} 
Verwandte Themen