【问题标题】:Symfony2 - How to set, and get, options when using a Form Class?Symfony2 - 使用表单类时如何设置和获取选项?
【发布时间】:2012-05-10 01:23:10
【问题描述】:

我正在使用表单类在我的项目中构建各种表单。

在 Entity Type 文件中,对于 buildForm 函数,有一个“array $options”的辅助参数(这在 Symfony 2 官方文档中有显示,但从未提及过!)

我已经将一个数组输入到控制器中的 createForm 函数中,但现在我完全不知道如何检索存储的值?

$form = $this->createForm(new ProductType(array(), array('id' => '2')), $product);

我发现获取选项的唯一方法是使用 getOption() 函数,但这在 Symfony 2 中不存在(我发现的帖子来自 2010 年)。

我尝试使用:

$id = $options['id'];

但是当我尝试在任何地方使用 $id 时,我得到了错误:

注意:未定义的索引:id

什么给了?

如何从 $options 数组中检索我的值?我是否一开始就正确设置它们?

编辑 - 更多代码:

表单类

<?php

namespace DEMO\DemoBundle\Form\Product;

use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;

class ProductType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('slug')
            ->add('reference')
            ->add('description')
            ->add('active_from')
            ->add('active_till')
            ->add('is_active')
            ->add('category', 'entity', array(
                'class' => 'DEMO\DemoBundle\Entity\Product\ProductCategory',
                'query_builder' => function(EntityRepository $er) {
                    return $er->createQueryBuilder('u')
                        ->where('u.section = :id')
                        ->setParameter('id', ***ID VARIABLE NEEDS TO GO HERE***)
                        ->orderBy('u.root', 'ASC')
                        ->addOrderBy('u.lft', 'ASC');
                },
                'empty_value' => 'Choose an option',
                'property' => 'indentedName',
            ));
    }

    public function getDefaultOptions()
    {
        return array(
            'data_class' => 'DEMO\DemoBundle\Entity\Product\Product'
        );
    }

    public function getName()
    {
        return 'demo_demobundle_product_type';
    }
}

【问题讨论】:

    标签: php symfony


    【解决方案1】:

    我认为您一开始就没有正确设置它们。您应该将它们作为第三个参数提供给createForm()

    编辑:这是您的表单类的外观:

    <?php
    namespace DEMO\DemoBundle\Form\Product;
    
    use Doctrine\ORM\EntityRepository;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilder;
    
    class ProductType extends AbstractType
    {
        public function buildForm(FormBuilder $builder, array $options)
        {
            $builder
                ->add('name')
                ->add('slug')
                ->add('reference')
                ->add('description')
                ->add('active_from')
                ->add('active_till')
                ->add('is_active')
                ->add('category', 'entity', array(
                    'class' => 'DEMO\DemoBundle\Entity\Product\ProductCategory',
                    'query_builder' => function(EntityRepository $er) use($options) {
                        return $er->createQueryBuilder('u')
                            ->where('u.section = :id')
                            ->setParameter('id', $options['id'])
                            ->orderBy('u.root', 'ASC')
                            ->addOrderBy('u.lft', 'ASC');
                    },
                    'empty_value' => 'Choose an option',
                    'property' => 'indentedName',
                ));
        }
    
        public function getDefaultOptions()
        {
            return array(
                'data_class' => 'DEMO\DemoBundle\Entity\Product\Product',
                'id'         => null
            );
        }
    
        public function getName()
        {
            return 'demo_demobundle_product_type';
        }
    }
    

    【讨论】:

    • 我相信 createForm() 的第三个选项是设置如下选项:“attr”、“by_reference”、“cascade_validation”、“csrf_field_name”、“csrf_protection”、“csrf_provider”、 “data”、“data_class”、“disabled”、“empty_data”、“error_bubbling”、“error_delay”、“error_mapping”、“error_type”、“field_error_type”、“help_block”、“help_inline”等(基本上,我试过,并显示“选项“id”不存在。”)
    • 您可以调整表单类的 getDefaultOptions() 方法来告诉您的表单有关此选项并避免此消息。
    • Tbh,我真的不想“破解”任何核心结构。函数 buildForm() 显然有一个辅助参数来设置一组选项。我想知道它是如何正确使用的。
    • 这不是破解核心结构,这是要走的路,getDefaultOptions() 是您的表单类中的一个方法(如果您使用 cli 任务生成表单)。它在那里,以便您可以修改它。如果您不相信我,请相信文档:symfony.com/doc/master/book/forms.html,其中显示了对此方法的修改示例。
    • 该页面没有显示如何自定义 getDefaultOptions()。它仅显示如何使用该方法的一些可用选项,例如 CSRF 保护和设置 data_class。请准确概述它在哪里显示了如何自定义允许我添加自己的参数的方法?
    【解决方案2】:

    让我告诉你什么对我有用

    在控制器中:

    $form = $this->createForm(new UsersType(), $entity, array(
        'attr' => array('locationId' => $currentLocationId)));
    

    在表单类型中:

    ->add('location', 'entity', array(
            'class' => 'Ro\RoinventBundle\Entity\Locations',
             'query_builder' => function (\Doctrine\ORM\EntityRepository $er) use ($options)
            {
                if (isset($options['attr']['locationId']) && ($options['attr']['locationId'] != NULL))
                {
                    return $er->createQueryBuilder('Locations')
                        ->where('Locations.id = :param')
                        ->setParameter('param', $options['attr']['locationId']);
                }
                //else do what you want
    },
    ));
    

    【讨论】:

      【解决方案3】:

      显然它不再是getDefaultOptions(),而是setDefaultOptions()

      否则它会说

      选项“my_custom_option”不存在。已知选项有:“action”、“attr”、“auto_initialize”、...

      所以,对我来说,我必须像这样更新 setDefaultOptions :

      public function setDefaultOptions(OptionsResolverInterface $resolver)
      {
          $resolver->setDefaults(array('my_custom_option' => false));
          // Others if needed, like in the documentation for : 'data_class' => 'VENDOR\Bundle\Entity\MyEntity', 'csrf_protection' => true
      }
      

      然后你可以在buildForm方法中检索它

      public function buildForm(FormBuilderInterface $builder, array $options)
      {
          $myCustomOption = $options['my_custom_option'];
      }
      

      【讨论】:

        【解决方案4】:

        据此Google Groups

        "greg0ire" 是对的,事实上我已经尝试过了,效果很好!!!。你说“我真的不想去“破解”任何核心结构”但你最终没有使用最好的方法。事实上,从我的角度来看,你最终做了你没有做的事情想做。

        所以最后你应该这样做:

        在表单类型

        public function buildForm(FormBuilder $builder, array $options)
        {
            $builder
                ->add('name')
                ->add('slug')
                ->add('reference')
                ->add('description')
                ->add('active_from')
                ->add('active_till')
                ->add('is_active')
                ->add('category', 'entity', array(
                    'class' => 'DEMO\DemoBundle\Entity\Product\ProductCategory',
                    'query_builder' => function(EntityRepository $er) {
                        return $er->createQueryBuilder('u')
                            ->where('u.section = :id')
                            ->setParameter('id', $options['id'])
                            ->orderBy('u.root', 'ASC')
                            ->addOrderBy('u.lft', 'ASC');
                    },
                    'empty_value' => 'Choose an option',
                    'property' => 'indentedName',
                ));
        }
        
        public function getDefaultOptions()
        {
            return array(
                'data_class' => 'DEMO\DemoBundle\Entity\Product\Product'
                'id' => null
            );
        }
        

        在控制器中

        $form = $this->createForm(new ProductType(), $product, array('id' => $id ));
        

        【讨论】:

          【解决方案5】:

          通过表单类__construct 方法传递选项,如下所示:

          use Doctrine\ORM\EntityRepository;
          use Symfony\Component\Form\AbstractType;
          use Symfony\Component\Form\FormBuilder;
          
          class ProductType extends AbstractType
          {
          
              private $options = array();
              public function buildForm(FormBuilder $builder, array $options)
              {
                  $builder
                      ->add('name')
                      ->add('slug')
                      ->add('reference')
                      ->add('description')
                      ->add('active_from')
                      ->add('active_till')
                      ->add('is_active')
                      ->add('category', 'entity', array(
                          'class' => 'DEMO\DemoBundle\Entity\Product\ProductCategory',
                          'query_builder' => function(EntityRepository $er) {
                              return $er->createQueryBuilder('u')
                                  ->where('u.section = :id')
                                  ->setParameter('id', $this->options['id'])
                                  ->orderBy('u.root', 'ASC')
                                  ->addOrderBy('u.lft', 'ASC');
                          },
                          'empty_value' => 'Choose an option',
                          'property' => 'indentedName',
                      ));
              }
          
              public function getDefaultOptions()
              {
                  return array(
                      'data_class' => 'DEMO\DemoBundle\Entity\Product\Product'
                  );
              }
          
              public function getName()
              {
                  return 'demo_demobundle_product_type';
              }
          
              public function __construct(array $options)
              {
                  $this->options = $options;
              }
          }
          

          然后你可以这样做:

          new ProductType(array('id'=>1));
          

          【讨论】:

          • 我尝试了这种方法,结果出现“未定义变量”错误。我完全复制了它,所以我无法弄清楚为什么会出现这个错误,就我而言,变量正在被设置......
          • 哈哈,是的,几天前已经想通了,看看我的回答:)谢谢你的帮助!
          【解决方案6】:

          好吧,事实证明,Gregoires 的答案非常接近,但在尝试实际但将变量放入 createQueryBuilder 函数时却给了我和“未定义的变量”错误。

          我花了一段时间试图找出原因并找到了问题所在。您必须在“query_builder”选项中为函数添加一个额外的参数,如下所示:

          'query_builder' => function(EntityRepository $er) use ($options) {
                              return $er->createQueryBuilder('u')
                                  ->where('u.section = :id')
                                  ->setParameter('id', $options['id'])
                                  ->orderBy('u.root', 'ASC')
                                  ->addOrderBy('u.lft', 'ASC');
                          },
          

          神奇的设置是“使用($options)”。这使您可以在查询生成器中成功使用 $options['id']。

          【讨论】:

          • 对不起,它实际上是用greg0ires答案实现的,我复制代码不正确。编辑它以清除它
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-19
          • 1970-01-01
          • 2013-08-01
          相关资源
          最近更新 更多