【问题标题】:How to set default value for form field in Symfony2?如何在 Symfony2 中设置表单字段的默认值?
【发布时间】:2011-12-16 07:39:06
【问题描述】:

有没有一种简单的方法可以为文本表单字段设置默认值?

【问题讨论】:

  • 是的,但是这个问题中给出的答案并不令人满意/不起作用......我将添加一个“编辑”来解释原因:-)
  • 您所追求的“完美”解决方案似乎是让字段具有“default_value”选项。问题是,currently it does not,所以我认为目前不存在您正在寻找的完美解决方案。 symfony 唯一提供的(见链接) data 选项。所以 if-then 是我能看到 atm 的唯一方法。即使字段本身有一个“default_value”选项,我想它在内部基本上也会做同样的事情。
  • 另外,我已经根据下面的 cmets 对方法 2 中的答案进行了更正。如果这解决了您在第 2 点中提到的语法问题,您可能需要编辑该注释。或者让我知道问题是什么,我会修正我的答案。
  • @Crone 这个问题是 2 年前提出的
  • @OndrejSlinták 我并没有投票结束,因为我是骗子,但仅供参考:不管哪个先来,"If the new question is a better question or has better answers, then vote to close the old one as a duplicate of the new one."

标签: php symfony


【解决方案1】:

您可以在模型类中为相关字段设置默认值(在映射定义中或自己设置值)。

此外,FormBuilder 让您有机会使用setData() 方法设置初始值。表单构建器被传递给表单类的 createForm() 方法。

另外,请查看此链接:http://symfony.com/doc/current/book/forms.html#using-a-form-without-a-class

【讨论】:

    【解决方案2】:

    可以在创建过程中轻松使用:

    ->add('myfield', 'text', array(
         'label' => 'Field',
         'empty_data' => 'Default value'
    ))
    

    【讨论】:

    • 对于 Symfony 2.1,我需要将 'data' 键更改为 'value'
    • 这不仅设置了一个默认值,它还将始终在任何上下文中强制该值。不是我所说的“默认值”...
    • 我不赞成这个解决方案,因为它不是问题的解决方案(正如上面提到的 Hubert Perron)。我试图在这篇文章中获得更好的解决方案stackoverflow.com/questions/17986481/…
    • 这是初始值,默认值为empty_data
    • data 没用 - 它会覆盖保存的值。 empty_data 不显示值,它在空值提交时使用它,并且无法保存未选中的选项。
    【解决方案3】:

    如果您需要设置默认值并且您的表单与实体相关,那么您应该使用以下方法:

    // buildForm() method
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
        ...
        ->add(
            'myField',
            'text',
            array(
                'data' => isset($options['data']) ? $options['data']->getMyField() : 'my default value'
            )
        );
    }
    

    否则,myField 将始终设置为默认值,而不是从实体中获取值。

    【讨论】:

    • 如果是数组而不是实体,只需将$options['data']->getMyField()替换为$option['data']['myField']
    • 我认为这是添加/更新的正确方法。但我讨厌 Symfony 让它过于复杂。
    • 这是唯一好的答案。当我查看文档时,我不明白其他答案。 empty_data :这个选项决定了当提交的值为空时,该字段将返回什么值。它没有设置初始值
    【解决方案4】:

    如果你的表单绑定到实体,只需使用构造方法在实体本身上设置默认值:

    public function __construct()
    {
        $this->field = 'default value';
    }
    

    【讨论】:

    • 即便如此,您的表单也可以有其他字段未映射到您的实体 ('mapped' => false)。对这些使用setData(...)
    【解决方案5】:

    默认值是通过配置相应的实体来设置的。在将实体绑定到表单之前,将其颜色字段设置为“#0000FF”:

    // controller action
    $project = new Project();
    $project->setColor('#0000FF');
    $form = $this->createForm(new ProjectType(), $project);
    

    【讨论】:

    • 这种方法有效,但缺点是每次使用表单类时都必须这样做,而且非常冗长(很多 set 语句)。由于表单组件非常优雅,因此肯定还有其他东西。不过还是谢谢 :-)
    • @jamie0726 在我看来,控制器有责任在新对象或获取对象时设置对象的值。这样你就可以让表单在不同的情况下使用不同的行为,例如,新的颜色可能会因为用户具有经理或超级经理角色而改变,并且由于这是一个业务逻辑,应该由控制器或服务,而不是表单。因此,正如 Cerad 所说,我也更喜欢这种解决方案。您始终可以创建一个服务来设置这些默认值,并在控制器中使用该服务使其保持干燥。
    • 这是我选择的解决方案,因为它符合我认为的逻辑。生成的控制器有不同的方法来创建 EDIT 和 CREATE 表单,这些是我为新实体设置默认/初始数据的地方。
    【解决方案6】:

    方法一(来自http://www.cranespud.com/blog/dead-simple-default-values-on-symfony2-forms/

    只需在您的实体中设置默认值,无论是在变量声明中还是在构造函数中:

    class Entity {
        private $color = '#0000FF';
        ...
    }
    

    class Entity {
        private $color;
    
        public function __construct(){
             $this->color = '#0000FF';
             ...
        }
        ...
    }
    

    来自上述链接中的评论的方法 2,以及来自 How to set default value for form field in Symfony2? 的 Dmitriy 的答案(不是接受的答案)

    使用FormBuilder添加字段时将默认值添加到data属性,改编自Dmitriy的回答。

    请注意,这假定属性将并且只会在它是新实体而不是现有实体时具有 null 值。

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->add('color', 'text', array(
                'label' => 'Color:',
                'data' => (isset($options['data']) && $options['data']->getColor() !== null) ? $options['data']->getColor() : '#0000FF'
            )
        );
    }
    

    【讨论】:

    • 第一个有效(谢谢!),第二个无效(对我来说): $options["data] 始终设置,因此永远不会使用默认值。我还在想如果解决方案 1 是预期的方法......
    • 你是对的 $options['data'] 总是被设置。如果您不初始化实体字段,则可以在该字段上测试 null ,例如。 'data' => $options['data']->getColor() !== null ?等等...假设 null 不是颜色字段的有效值,因此现有实体永远不会有该字段的 null 值。
    • 啊,愚蠢的我:我用 'isset($ $options['data']->getColor())' 尝试过,我收到一条错误消息,提示“在书写上下文中使用它不是允许”并忘记了我必须以不同的方式检查它:-)
    • 实际上似乎确实存在未设置数据条目的情况。更安全地测试两者,即 isset($options['data']) && $options['data']->getColor() !== null ? ...
    【解决方案7】:

    只是为了让我理解问题。

    您想根据实体中的数据调整表单的构建方式。如果正在创建实体,则使用一些默认值。如果实体存在,则使用数据库值。

    就个人而言,我认为@MolecularMans 的解决方案是可行的方法。我实际上会在构造函数或属性语句中设置默认值。但你似乎不喜欢这种方法。

    您可以按照以下方式操作:http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

    您在表单类型上挂了一个监听器,然后您可以检查您的实体并根据新的或现有的实体相应地调整构建器->添加语句。您仍然需要在某处指定默认值,尽管您可以在侦听器中对其进行编码。或者将它们传递给表单类型。

    虽然看起来工作量很大。最好将实体传递给已设置默认值的表单。

    【讨论】:

      【解决方案8】:

      我过去曾多次考虑过这一点,所以我想我会记下我曾经/使用过的不同想法。有些东西可能有用,但没有一个是“完美”的 Symfony2 解决方案。

      构造函数 在实体中,您可以执行 $this->setBar('default value');但是每次加载实体(db 与否)时都会调用它,并且有点混乱。但是,它适用于每种字段类型,因为您可以创建日期或您需要的任何其他内容。

      get 中的 If 语句 我不会,但你可以。

      return ( ! $this->hasFoo() ) ? 'default' : $this->foo;
      

      工厂/实例。 调用一个静态函数/二级类,它为您提供一个预先填充了数据的默认实体。例如。

      function getFactory() {
          $obj = new static();
          $obj->setBar('foo');
          $obj->setFoo('bar');
      
         return $obj;
      }
      

      如果您添加额外的字段,您将不得不维护此功能,这并不理想,但这确实意味着您将数据设置器/默认值与从 db.同样,如果您需要不同的默认数据,您可以拥有多个 getFactories。

      扩展/反射实体 创建一个扩展实体(例如 FooCreate extends Foo),它在创建时为您提供默认数据(通过构造函数)。类似于工厂/实例的想法只是一种不同的方法 - 我个人更喜欢静态方法。

      在构建表单之前设置数据 在构造函数/服务中,您知道您是否有一个新实体,或者它是否是从数据库中填充的。因此,当您抓取一个新实体时,在不同字段上调用集合数据是合理的。例如。

      if( ! $entity->isFromDB() ) {
           $entity->setBar('default');
           $entity->setDate( date('Y-m-d');
           ...
      }
      $form = $this->createForm(...)
      

      表单事件 创建表单时,您在创建字段时设置默认数据。您覆盖此使用 PreSetData 事件侦听器。这样做的问题是您正在复制表单工作量/复制代码并使其更难维护/理解。

      扩展形式 类似于 Form 事件,但您根据它是否为 db / new 实体调用不同的类型。我的意思是你有 FooType 定义你的编辑表单, BarType 扩展了 FooType 并将所有数据设置到字段中。然后,在您的控制器中,您只需选择要启动的表单类型。如果您有自定义主题并且喜欢事件,这很糟糕,这会为我的喜好创建过多的维护。

      树枝 当您基于每个字段执行此操作时,您也可以使用 value 选项创建自己的主题并默认数据。如果您希望保持模板干净并且表单可重用,那么没有什么能阻止您将其包装到表单主题中。例如

      form_widget(form.foo, {attr: { value : default } });
      

      JS 如果字段为空,则使用 JS 函数填充表单很简单。例如,您可以使用占位符做一些事情。这是一个坏主意。

      表单即服务 对于我所做的一个基于表单的大型项目,我创建了一个服务,它生成所有表单,完成所有处理等。这是因为表单将在多个环境中的多个控制器中使用,而表单是生成/处理的同样,它们以不同的方式显示/交互(例如错误处理、重定向等)。这种方法的美妙之处在于,您可以默认数据、执行您需要的所有操作、通用处理错误等,所有这些都被封装在一个地方。

      结论 正如我所看到的,您会一次又一次地遇到同样的问题——默认数据在哪里?

      • 如果您将其存储在 db/doctrine 级别,如果您不想每次都存储默认值会怎样?
      • 如果您将其存储在实体级别,如果您想在其他地方重新使用该实体而其中没有任何数据,会发生什么情况?
      • 如果您将其存储在实体级别并添加一个新字段,您是否希望以前的版本在编辑时具有该默认值?数据库中的默认设置也是如此...
      • 如果您将其存储在表单级别,那么在您以后维护代码时是否显而易见?
      • 如果它在构造函数中,如果在多个地方使用表单会发生什么?
      • 如果您将其推送到 JS 级别,那么您已经走得太远了 - 数据不应该在视图中,更不用说 JS(我们忽略了兼容性、呈现错误等)
      • 如果您像我一样在多个地方使用它,该服务非常棒,但对于一个站点上的简单添加/编辑表单来说,它是多余的...

      为此,我每次都以不同的方式处理这个问题。例如,在创建表单之前,可以在构造函数中轻松(并且合乎逻辑地)设置注册表单“newsletter”选项。当我构建链接在一起的表单集合(例如,不同表单类型中的哪些单选按钮链接在一起)时,我使用了事件监听器。当我构建了一个更复杂的实体(例如,一个需要子实体或大量默认数据的实体)时,我使用了一个函数(例如“getFactory”)来根据需要创建它的元素。

      我认为没有一种“正确”的方法,因为每次我有这个要求时都会略有不同。

      祝你好运!我希望无论如何我已经给了你一些深思熟虑,并且没有过多地闲逛;)

      【讨论】:

      • 您能否更详细地说明您对“生成所有表单的服务”的含义?我现在也在做一个真正以表单为中心的项目,如果有的话会很棒不同的观点。
      • 使用原则时,从数据库加载实体时不会调用构造函数。
      【解决方案9】:

      您可以设置默认值,例如对于message 的形式,像这样:

      $defaultData = array('message' => 'Type your message here');
      $form = $this->createFormBuilder($defaultData)
          ->add('name', 'text')
          ->add('email', 'email')
          ->add('message', 'textarea')
          ->add('send', 'submit')
          ->getForm();
      

      如果你的表单被映射到一个实体,你可以这样(例如默认用户名):

      $user = new User();
      $user->setUsername('John Doe');
      
      $form = $this->createFormBuilder($user)
          ->add('username')
          ->getForm();
      

      【讨论】:

      • 我更喜欢这种方法,特别是因为在大多数应用程序中,您正在创建一个表单并传入一个表单处理的实体。
      【解决方案10】:

      我的解决方案:

      $defaultvalue = $options['data']->getMyField();
      $builder->add('myField', 'number', array(
                  'data' => !empty($defaultvalue) ? $options['data']->getMyField() : 0
              )) ;
      

      【讨论】:

        【解决方案11】:

        你可以用empty_data设置默认值

        $builder->add('myField', 'number', ['empty_data' => 'Default value'])
        

        【讨论】:

        • 设置数据不是设置默认值。这个答案是正确的。
        • 这似乎只在提交时将字段设置为 1 没有值。当您希望表单在没有值的情况下默认在输入中显示 1 时呢?
        • 在我的测试中,empty_data 不允许我覆盖提交为空的字段的默认值,例如如果您想将数据库保存为 0 而不是 NULL。据我所知,这个错误仍然很突出:github.com/symfony/symfony/issues/5906
        【解决方案12】:

        如果该字段绑定到实体(是该实体的属性),您可以为其设置默认值。

        一个例子:

        public function getMyField() {
            if (is_null($this->MyField)) {
                $this->setMyField('my default value');
            }
            return $this->MyField;
        }
        

        【讨论】:

          【解决方案13】:

          通常,对于表单的初始默认值,我使用固定装置。当然,这种方式并不简单,但很舒服。

          例子:

          class LoadSurgeonPlanData implements FixtureInterface
          {
              public function load(ObjectManager $manager)
              {
                  $surgeonPlan = new SurgeonPlan();
          
                  $surgeonPlan->setName('Free trial');
                  $surgeonPlan->setPrice(0);
                  $surgeonPlan->setDelayWorkHours(0);
                  $surgeonPlan->setSlug('free');
          
                  $manager->persist($surgeonPlan);
                  $manager->flush();        
              }   
          }
          

          然而,symfony 类型字段有data 选项。

          例子

          $builder->add('token', 'hidden', array(
              'data' => 'abcdef',
          ));
          

          【讨论】:

            【解决方案14】:

            有一个非常简单的方法,你可以在这里设置默认值:

            $defaults = array('sortby' => $sortby,'category' => $category,'page' => 1);
            
            $form = $this->formfactory->createBuilder('form', $defaults)
            ->add('sortby','choice')
            ->add('category','choice')
            ->add('page','hidden')
            ->getForm();
            

            【讨论】:

              【解决方案15】:

              我通常只是为我的实体中的特定字段设置默认值:

              /**
               * @var int
               * @ORM\Column(type="integer", nullable=true)
               */
              protected $development_time = 0;
              

              这适用于新记录或仅更新现有记录。

              【讨论】:

              • 'empty_data' 是一个回调用于允许实体上的构造函数参数时,这似乎不起作用。
              【解决方案16】:

              如果你在 symfony 2.7 中使用 FormBuilder 来生成表单,你也可以将初始数据传递给 Controler 的 createFormBuilder 方法

              $values = array(
                  'name' => "Bob"
              );
              
              $formBuilder = $this->createFormBuilder($values);
              $formBuilder->add('name', 'text');
              

              【讨论】:

                【解决方案17】:
                ->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
                     $form = $event->getForm(); 
                     $data = $event->getData(); 
                
                     if ($data == null) {
                         $form->add('position', IntegerType::class, array('data' => 0));
                     }
                
                });
                

                【讨论】:

                • 这是一个不错的解决方案。调用 $event->setData() 而不是读取该字段可能会更好。
                【解决方案18】:

                任何情况/方法的通用解决方案,主要通过使用没有类的表单或当我们需要访问任何服务来设置默认值时:

                // src/Form/Extension/DefaultFormTypeExtension.php
                
                class DefaultFormTypeExtension extends AbstractTypeExtension
                {
                    public function buildForm(FormBuilderInterface $builder, array $options)
                    {
                        if (null !== $options['default']) {
                            $builder->addEventListener(
                                FormEvents::PRE_SET_DATA,
                                function (FormEvent $event) use ($options) {
                                    if (null === $event->getData()) {
                                        $event->setData($options['default']);
                                    }
                                }
                            );
                        }
                    }
                
                    public function configureOptions(OptionsResolver $resolver)
                    {
                        $resolver->setDefault('default', null);
                    }
                
                    public function getExtendedType()
                    {
                        return FormType::class;
                    }
                }
                

                并注册表单扩展:

                app.form_type_extension:
                    class: App\Form\Extension\DefaultFormTypeExtension
                    tags:
                        - { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }
                

                之后,我们可以在任何表单域中使用default 选项:

                $formBuilder->add('user', null, array('default' => $this->getUser()));
                $formBuilder->add('foo', null, array('default' => 'bar'));
                

                【讨论】:

                • 这应该被接受为最佳答案(最新)
                【解决方案19】:

                正如布赖恩所问:

                empty_data 似乎仅在提交时将字段设置为 1 没有值。 当您希望表单默认显示 1 在 没有值时输入?

                你可以用empty_value设置默认值

                $builder->add('myField', 'number', ['empty_value' => 'Default value'])
                

                【讨论】:

                  【解决方案20】:

                  如果您在创建表单中设置“数据”,则在编辑实体时不会修改此值。

                  我的解决办法是:

                  public function buildForm(FormBuilderInterface $builder, array $options) {
                      // In my example, data is an associated array
                      $data = $builder->getData();
                  
                      $builder->add('myfield', 'text', array(
                       'label' => 'Field',
                       'data' => array_key_exits('myfield', $data) ? $data['myfield'] : 'Default value',
                      ));
                  }
                  

                  再见。

                  【讨论】:

                  • 比公认的答案更有帮助!如果您使用 PHP7+,您可以通过以下方式使其更加整洁:'data' => $data['myfield'] ?? 'Default value',
                  • 你在 array_key_exists() 函数中有错字
                  【解决方案21】:

                  不要使用:

                  'data' => 'Default value'
                  

                  在这里阅读:https://symfony.com/doc/current/reference/forms/types/form.html#data

                  "data 选项在渲染时总是覆盖取自域数据(对象)的值。这意味着当表单编辑一个已经持久化的对象时,对象值也会被覆盖,导致它在表单已提交。”


                  使用以下内容:

                  假设,对于这个例子,你有一个实体 Foo,并且有一个“活动”字段(在这个例子中是 CheckBoxType,但过程与其他所有类型相同),你希望默认检查它

                  在你的 FooFormType 类中添加:

                  ...
                  use Symfony\Component\Form\FormEvent;
                  use Symfony\Component\Form\FormEvents;
                  ...
                  public function buildForm( FormBuilderInterface $builder, array $options )
                  {
                      ...
                  
                      $builder->add('active', CheckboxType::class, array(
                          'label' => 'Active',
                      ));
                  
                      $builder->addEventListener(
                          FormEvents::PRE_SET_DATA,
                          function(FormEvent $event){                 
                              $foo = $event->getData();
                              // Set Active to true (checked) if form is "create new" ($foo->active = null)
                              if(is_null($foo->getActive())) $foo->setActive(true);
                          }
                     );
                  }
                  public function configureOptions( OptionsResolver $resolver )
                  {
                      $resolver->setDefaults(array(
                          'data_class' => 'AppBundle:Foo',
                      ));
                  }
                  

                  【讨论】:

                  • 这是钱!!使用表单事件侦听器在默认值之前检查您的值。这应该是表单中默认值的公认答案,因为它适用于新建操作和编辑操作。
                  • 这是处理这个问题的正确方法,这应该是公认的答案。
                  • 如果您使用条件/三元,则您在开头提到的内容不正确。像这样:'data' => $data['myfield'] ?? 'Default value'
                  【解决方案22】:

                  我通过在 attr 中添加 value 解决了这个问题:

                  ->add('projectDeliveringInDays', null, [
                      'attr' => [
                            'min'=>'1',
                            'value'=>'1'
                            ]
                       ])
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2015-01-26
                    • 1970-01-01
                    • 2012-04-13
                    • 2019-06-03
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-12-04
                    • 1970-01-01
                    相关资源
                    最近更新 更多