2017-01-23 70 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