2017-01-23 75 views
0

我有兩個實體,發票和InvoiceItem在yml中定義如下。奇怪的學說實體行爲

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 

我的控制器接收發票細節並保存元件如下圖所示

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呈現發票詳細信息,包括項目和扣減項目。

..... 

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

我遇到的挑戰是發送到模板的$ invoice對象沒有任何項目或扣減應該是集合。我檢查了數據庫,可以確認這些項目和扣減項目是否保留在相應的表格中,因此我不明白爲什麼表格中沒有invoice.items或invoice.deductions。

絕望之餘,我在每個InvoiceItem對象創建思想後都刷新了,可能在持久化事務完成之前呈現模板,但這也沒有幫助。

+0

仔細檢查發票項目數據庫表。我懷疑invoice_id是NULL? – Cerad

回答

0

UPDATE:

至少我已經發現了一個其他錯誤是joinColumn下所定義的onDelete選項。它應該是:

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

--------

如果您有隻有當createInvoiceAction在視圖呈現這個問題,那麼問題可能是因爲你不」實際上通過名爲類似於addItem()的方法將InvoiceItem添加到發票對象中(命名取決於您如何命名發票實體中的關係),那些項目可能僅在下次發票實體中存在你查詢發票,因爲即使你已經設置了每個項目的發票,也可能是因爲如果這些實體剛剛創建,教義可能無法使用pro檢索它們xy類。因此,解決辦法是簡單:使用發票實體AddItem方法來添加項目到發票,然後不要忘記添加設置一個方法

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

    return $this; 
} 

但是裏面的給定商品發票邏輯如果在下一次查詢已保存的發票及其項目時仍存在此問題,則建議您檢查該對象是否實際包含getter方法,而不是簡單地嘗試通過公共屬性訪問項目。換句話說,在invoice類中,名爲items的屬性應該被定義爲private,並且你應該有一個getItems()方法來檢索這些項目。 與教條一起使用的對象必須具有這些方法,因爲它使用其代理類來覆蓋這些方法內部的邏輯,以便添加代碼,這些代碼還會發出查詢以從數據庫中檢索InvoiceItem(s)將它們放置在對象的私有屬性中,然後只在類中運行getter代碼。如果沒有這些方法,私有屬性將保持空白,因爲沒有其他方法可以讓教條從數據庫中爲您檢索它們(除非可能獲取:「EAGER」)。

+0

感謝您抽出寶貴時間對此進行審查。我已經嘗試了第一個建議,但沒有奏效。 這種行爲真的很奇怪,只是似乎是控制器級別的問題,使用Sonata Admin,我能夠使用getter方法訪問發票項目,但在控制器中不能使用。 –

+0

我注意到InvoiceItem.yml文件的縮進錯誤。您正在將級聯刪除定義爲joinColumns之一。我相應地更新了我的答案。希望這可以幫助 :) – grssn