2017-01-23 4 views
0

Ich habe zwei Entitäten, Invoice und InvoiceItem definiert wie folgt in Yml.Weird Doctrine Entity Behavior

Invoice.orm.yml

AppBundle\Entity\Invoice: 
type: entity 
table: invoices 
repositoryClass: AppBundle\Repository\InvoiceRepository 
fields: 
    id: 
     id: true 
     type: integer 
     generator: 
      strategy: AUTO 
    ...... 

oneToMany: 
    items: 
    targetEntity: InvoiceItem 
    mappedBy: invoice 
    deductions: 
    targetEntity: InvoiceDeduction 
    mappedBy: invoice 
    payments: 
    targetEntity: InvoicePayment 
    mappedBy: invoice 

InvoiceItem.orm.yml

AppBundle\Entity\InvoiceItem: 
type: entity 
table: invoice_items 
repositoryClass: AppBundle\Repository\InvoiceItemRepository 
fields: 
    id: 
     id: true 
     type: integer 
     generator: 
      strategy: AUTO 
.... 
manyToOne: 
    invoice: 
    targetEntity: Invoice 
    inversedBy: items 
    joinColumn: 
     invoice_id: 
     referencedColumnName: id 
     onDelete: CASCADE 

Mein Controller empfängt Rechnungsdaten und speichert die Elemente, wie unten dargestellt

public function createInvoiceAction(Request $request) 
{ 
    .... 
    $invoice = new Invoice(); 
    $invoice->setReference($ref); 
    $invoice->setInvoiceDate(\DateTime::createFromFormat('d/m/Y',$request->query->get('invoiceDate'))); 
    $invoice->setDescription($request->query->get('summary')); 
    $invoice->setAttn($request->query->get('att')); 
    $invoice->setIsVatable($request->query->get('vattable') == 'true' ? 1 : 0); 
    $invoice->setAdditionalInstructions($request->query->get('additional')); 
    $invoice->setJob($job); 
    $invoice->setCurrency($request->query->get('currency')); 
    $invoice->setGeneratedBy($createdBy); 
    $invoice->setFile($filename); 
    $job->setStatus('Invoiced'); 
    $em->persist($invoice); 
    $em->persist($job); 
    $em->flush(); 

    $items = $request->query->get('items'); 
    for($i=0;$i<count($items);$i++) 
    { 
     if($items[$i]['description']!= '' && $items[$i]['amount'] != '') 
     { 
     $item = new InvoiceItem(); 
     $item->setDescription($items[$i]['description']); 
     $item->setAmount($items[$i]['amount']); 
     $item->setInvoice($invoice); 
     $em->persist($item); 
     $em->flush(); 
     } 
    } 

    $deductions = $request->query->get('deductions'); 
    for($i=0;$i<count($deductions);$i++) 
    { 
     if($deductions[$i]['description'] != '' && $deductions[$i]['value'] != '') 
     { 
     $deduction = new InvoiceDeduction(); 
     $deduction->setDescription($deductions[$i]['description']); 
     $deduction->setValue($deductions[$i]['value']); 
     $deduction->setIsPercentage($deductions[$i]['isPercentage'] == 'true' ? 1 : 0); 
     $deduction->setInvoice($invoice); 
     $em->persist($deduction); 
     $em->flush(); 
     } 
    } 

    $html = $this->renderView('AppBundle:Default:invoice.html.twig', array('invoice' => $invoice)); 

    return new Response(
     $html 
    ); 
} 

invoice.html .twig, die die Rechnungsdetails einschließlich Posten und Abzüge darstellt.

..... 

{% for item in invoice.items %} 
    <tr> 
     <td>{{ loop.index }}</td> 
     <td>{{ item.description }}</td> 
     <td>{{ item.amount|number_format(0, '', ',') }}</td> 
    </tr> 
{% endfor %} 
..... 

Die Herausforderung, die ich habe, ist, dass die $ Rechnung Objekt an der Vorlage gesendet wird, hat keine Artikel oder Abzüge, die angeblich Sammlungen sein. Ich habe in der Datenbank eingecheckt und kann bestätigen, dass die Artikel und Abzüge in den entsprechenden Tabellen beibehalten werden, so dass ich nicht verstehe, warum es keine Rechnung oder Rechnungen in den Tabellen gibt.

Aus Verzweiflung Ich flushed nach jeder InvoiceItem-Objekt-Erstellung denken, dass die Vorlage möglicherweise gerendert wurde, bevor die Persist-Transaktion abgeschlossen wurde, aber das hat auch nicht geholfen.

+0

Überprüfen Sie die Datenbanktabelle der Rechnungspositionen. Ich vermute, dass invoice_id NULL ist? – Cerad

Antwort

0

UPDATE:

Atleast ein anderer Fehler, den ich entdeckt habe, ist die onDelete Option unter joinColumn definiert ist. Es sollte sein:

manyToOne: 
    invoice: 
    targetEntity: Invoice 
    inversedBy: items 
    joinColumn: 
     invoice_id: 
     referencedColumnName: id 
    onDelete: CASCADE 

--------

Wenn Sie dieses Problem nur mit, wenn die Sicht während createInvoiceAction gemacht wird, dann könnte das Problem, dass, da Sie don‘ t das InvoiceItem dem Invoice-Objekt über eine Methode namens addItem() hinzufügen (die Benennung hängt davon ab, wie Sie die Relation in der Rechnungsentität benennen), diese Elemente sind möglicherweise erst beim nächsten Mal in der Invoice-Entität vorhanden Sie fragen die Rechnung ab, denn auch wenn Sie die Rechnung für jeden Artikel festgelegt haben, kann es sein, dass die Doktrin sie möglicherweise nicht mit dem Profi abrufen konnte, wenn diese Entitäten gerade erstellt wurden xy Klassen. So wäre die Lösung einfach sein: die addItem Methode auf Rechnung Einheit verwenden Sie die Elemente in der Rechnung hinzuzufügen und dann vergessen Sie nicht die Logik hinzufügen, die die Rechnung für das gegebene Element stellt innerhalb dieser Methode

public function addItem(InvoiceItem $item) 
{ 
    $item->setInvoice($this); 
    $this->items[] = $item; 

    return $this; 
} 

jedoch Wenn dieses Problem bei der nächsten Abfrage der bereits beibehaltenen Rechnung und ihrer Elemente weiterhin besteht, sollten Sie überprüfen, ob das Objekt tatsächlich die Getter-Methoden enthält, und Sie nicht einfach versuchen, über eine öffentliche Eigenschaft auf die Elemente zuzugreifen. Mit anderen Worten, innerhalb der Rechnungsklasse sollten die Eigenschaften benannten Elemente als privat definiert werden, und Sie sollten eine getItems() -Methode haben, die die Elemente abruft. Objekte, die mit der Doktrin verwendet werden, müssen diese Methoden haben, da sie die Logik innerhalb dieser Methoden mit ihren Proxy-Klassen überschreiben, um Code hinzuzufügen, der auch die Abfrage sendet, um in Ihrem Fall InvoiceItem (s) aus der Datenbank und Platziere sie innerhalb der privaten Eigenschaft des Objekts und führe dann den Getter-Code innerhalb deiner Klasse aus. Ohne diese Methoden würden private Eigenschaften leer bleiben, da es für die Doktrin keine andere Möglichkeit gibt, sie aus der Datenbank für Sie abzurufen (außer vielleicht: "EAGER").

+0

Vielen Dank, dass Sie sich die Zeit genommen haben, dies zu überprüfen. Ich hatte den ersten Vorschlag schon ausprobiert, aber es hat nicht funktioniert. Dieses Verhalten ist wirklich seltsam und scheint nur ein Problem auf Controller-Ebene, mit Sonata Admin, ich bin in der Lage, Rechnung Elemente mit Getter-Methode zugreifen, aber das gleiche wird nicht auf der Steuerung arbeiten. –

+0

Ich habe einen Fehler beim Einrücken Ihrer InvoiceItem.yml-Datei festgestellt. Sie definieren Kaskadenlöschung als eine der JoinColumns. Ich habe meine Antwort entsprechend aktualisiert. Hoffe das hilft :) – grssn

Verwandte Themen