【问题标题】:Generating symfony forms with an array instead of entity?使用数组而不是实体生成 symfony 表单?
【发布时间】:2016-05-09 14:28:22
【问题描述】:

我正在尝试生成一个我认为只需要两个实体的表单。然而,我设法让它工作的唯一方法是使用三个。我的表格有效,但速度很慢,因为每个实体的数据库中有很多记录。有没有更聪明的方法来处理这个问题?

我想要实现的是数据库中每个 customer 实体的嵌套InvoiceType 表单。然后,管理员用户应该能够勾选/取消勾选他们想要为其生成一批发票的客户。它应该看起来像这样:

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

目前,我使用三个实体使其工作。我创建了一个 Invoicebatch 实体,以识别 Invoice 属于哪个批次(如果有)。但是,由于我需要为数据库中的每个 Customer 创建一个新的 Invoice 对象,因此我将(我认为)每个 Customer 对象加载到我的控制器中的表单对象中:

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')
}

我的 InvoiceBatchType 如下:

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,
            ))
        ;
    }

我的 InvoiceForBulkType 是:

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,
            ))
        ;
    }
}

我在想可能只是将客户名称作为数组加载,因为我只想在每一行上显示一个客户名称(即没有下拉列表或其他表单元素)。我已经尝试了一些尝试,但没有运气,所以我认为 $customer 对象需要包含在我不知道的 Symfony 中的后台进程中(我在 CustomerOneToMany 关联/kbd> 和 发票)。

【问题讨论】:

  • 首先删除问题的“我认为”部分。检查 Web 调试工具栏以确定实际执行的查询。
  • 好点谢谢@Cerad - Doctrine=7ms (90MB), controller=37,325ms (937MB), twig files=20,806ms (937MB), kernel response=79ms (937MB)
  • 您是否确认正在执行数千个查询?
  • 数据库只有三个查询——第三个是获取最终输入$form 的客户对象的查询。虽然看起来不错,但在 7ms 时。虽然仍然是 Web 开发的新手,但拥有近 1GB 的控制器似乎很大 - 这是在“正常范围”内还是我在那里做错了什么?
  • 你检查过'entity'类型和expanded=>true和multiple=>true吗?

标签: arrays forms symfony


【解决方案1】:

我最终设法让它工作了——问题是我不知道在 Symfony 表单中传递实体的选项。我试图总结下面的理论/逻辑,希望它对其他努力理解 Symfony 形式的人有所帮助:

通读Symfony Form documentation 我错误地认为只有EntityTypeCollectionType 可以处理接收实体作为输入。因此,我的InvoiceForBatchType 导致了问题 - 它正在将所有 Customers 加载到每个 Invoice 中。

我在 Symfony 表单中缺少的关键概念是:

如果您传递一个您希望能够访问的实体,那么您不要使用EntityType(除非您想填充下拉菜单/收音机/刻度)。相反,您创建一个新文件来定义嵌套的 FormType

在我的情况下,这是一个简单的解决方法:

1. 将 InvoiceForBulkType 更新为:
class InvoiceForBulkType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            /* ... */

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

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

    /* ... */
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    • 2013-03-12
    • 2014-04-09
    • 2015-11-01
    • 1970-01-01
    • 2014-06-08
    相关资源
    最近更新 更多