如何在Symfony2中设置表单字段的默认值?

Ond*_*ták 134 php symfony

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

rkm*_*max 115

您可以使用设置默认值 empty_data

$builder->add('myField', 'number', ['empty_data' => 'Default value'])
Run Code Online (Sandbox Code Playgroud)

  • 设置数据未设置默认值.这个答案是正确的. (29认同)
  • 这似乎只在提交时没有值将字段设置为1.当没有值时,您希望表单默认在输入中显示1时怎么办? (9认同)

web*_*a2l 103

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

->add('myfield', 'text', array(
     'label' => 'Field',
     'empty_data' => 'Default value'
))
Run Code Online (Sandbox Code Playgroud)

  • 这不仅会设置默认值,还会始终强制在任何上下文中使用该值.不是我称之为"默认值"...... (173认同)
  • 这是初始值,默认值为`empty_data` (13认同)
  • 对于Symfony 2.1,我需要将`'data''键更改为''value' (10认同)
  • 我赞成这个解决方案,因为它不是问题的解决方案(正如上面提到的Hubert Perron所述).我想在这篇文章中找到更好的解决方案http://stackoverflow.com/questions/17986481/set-default-values-using-form-classes-in-symfony-2 (4认同)
  • `data`没用 - 它会覆盖保存的值.`empty_data`没有显示值,它在空值提交时使用它,并且无法保存未选中的选项. (3认同)
  • @Edd你确定吗?只是试图在Symfony 2.1.5-DEV中输入`value`不起作用.但是`data`工作得很好. (2认同)
  • 我再次问了这个问题并得到了一个非凡的答案:http://stackoverflow.com/questions/17986481/set-default-values-using-form-classes-in-symfony-2 (2认同)

ste*_*ton 63

我过去曾经想过这几次,所以我想记下我曾经使用过的不同想法.有些东西可能有用,但没有一个是"完美的"Symfony2解决方案.

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

如果get中的陈述 我不会,但你可以.

return ( ! $this->hasFoo() ) ? 'default' : $this->foo;
Run Code Online (Sandbox Code Playgroud)

工厂/实例.调用静态函数/辅助类,它为您提供预先填充数据的默认实体.例如

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

   return $obj;
}
Run Code Online (Sandbox Code Playgroud)

如果你添加额外的字段,你必须保持这个功能,这不是很理想,但它确实意味着你要分离数据设置器/默认值和从数据库生成的数据.同样,如果您需要不同的默认数据,您可以拥有多个getFactories.

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

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

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

表单事件 创建表单时,您在创建字段时设置默认数据.您重写此使用PreSetData事件侦听器.这样做的问题在于,您正在复制表单工作负载/重复代码并使其难以维护/理解.

扩展表单 与表单事件类似,但根据它是否为db/new实体,您可以调用不同的类型.我的意思是你有FooType定义你的编辑形式,BarType扩展FooType这个并将所有数据设置为字段.在您的控制器中,您只需选择要激发的表单类型.如果你有一个自定义主题,并且喜欢事件,那就太糟糕了,为我的喜好创造了太多的维护.

Twig 您可以创建自己的主题,并在每个字段的基础上使用值选项默认数据.如果您希望保持模板清洁并且表单可重用,则无法阻止您将其包装到表单主题中.例如

form_widget(form.foo, {attr: { value : default } });
Run Code Online (Sandbox Code Playgroud)

JS 如果字段为空,用JS函数填充表单是很简单的.例如,您可以使用占位符执行某些操作.这是一个糟糕的坏主意.

表单即服务 对于我所做的一个基于表单的大型项目,我创建了一个生成所有表单,执行所有处理等的服务.这是因为表单将在多个环境中的多个控制器中使用,而表单则是以相同的方式生成/处理它们,以不同方式显示/交互(例如错误处理,重定向等).这种方法的优点在于您可以默认数据,执行所需的一切,一般地处理错误等等,并且它们都封装在一个地方.

结论 在我看来,你会一次又一次地遇到同样的问题 - 默认数据存在于哪里?

  • 如果将它存储在db/doctrine级别,如果您不想每次都存储默认值,会发生什么?
  • 如果您将其存储在实体级别,如果您想在其他地方重新使用该实体而没有任何数据,会发生什么?
  • 如果将其存储在实体级别并添加新字段,您是否希望以前的版本在编辑时具有该默认值?同样适用于DB中的默认值...
  • 如果将它存储在表单级别,那么在以后维护代码时这是否显而易见?
  • 如果它在构造函数中,如果您在多个位置使用该表单会发生什么?
  • 如果你把它推到JS级别然后你已经走得太远 - 数据不应该在视图中从不介意JS(我们忽略了兼容性,渲染错误等)
  • 如果像我这样你在多个地方使用它,这项服务很棒,但是在一个网站上添加/编辑表单太过分了......

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

我不认为有一种"正确"的方法,因为每次我有这个要求时,它都会略有不同.

祝好运!我希望无论如何我都给了你一些思考的食物而且没有过多地絮絮叨叨;)

  • 在使用doctrine时,从db加载实体时不会调用构造函数. (2认同)

Dmi*_*riy 42

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

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

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

  • 我认为这是添加/更新的正确方法.但我讨厌Symfony让它太复杂了. (3认同)

Jak*_*las 19

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

此外,FormBuilder使您可以使用setData()方法设置初始值.表单构建器将传递给表单类的createForm()方法.

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


Hub*_*ron 16

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

public function __construct()
{
    $this->field = 'default value';
}
Run Code Online (Sandbox Code Playgroud)


cry*_*lus 12

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

只需在变量声明或构造函数中设置实体的默认值:

class Entity {
    private $color = '#0000FF';
    ...
}
Run Code Online (Sandbox Code Playgroud)

要么

class Entity {
    private $color;

    public function __construct(){
         $this->color = '#0000FF';
         ...
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

从上面链接中的注释中获取方法2,以及如何在Symfony2中为表单字段设置默认值的 Dmitriy的答案(不是可接受的答案)

使用FormBuilder添加字段时,将默认值添加到数据属性,并根据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'
        )
    );
}
Run Code Online (Sandbox Code Playgroud)


Got*_*bel 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();
Run Code Online (Sandbox Code Playgroud)

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

$user = new User();
$user->setUsername('John Doe');

$form = $this->createFormBuilder($user)
    ->add('username')
    ->getForm();
Run Code Online (Sandbox Code Playgroud)

  • 我更喜欢这种方法,特别是因为在大多数应用程序中,您正在创建表单并传入表单处理的实体. (2认同)

yce*_*uto 9

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

// 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

并注册表单扩展名:

app.form_type_extension:
    class: App\Form\Extension\DefaultFormTypeExtension
    tags:
        - { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }
Run Code Online (Sandbox Code Playgroud)

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

$formBuilder->add('user', null, array('default' => $this->getUser()));
$formBuilder->add('foo', null, array('default' => 'bar'));
Run Code Online (Sandbox Code Playgroud)


zii*_*web 6

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

});
Run Code Online (Sandbox Code Playgroud)


cur*_*e85 6

不要使用:

'data' => 'Default value'
Run Code Online (Sandbox Code Playgroud)

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

“数据选项在呈现时始终会覆盖从域数据(对象)获取的值。这意味着当表单编辑一个已保留的对象时,对象值也会被覆盖,从而在提交表单时会丢失其保留的值。”


使用以下内容:

可以说,在此示例中,您有一个Entity Foo,并且有一个字段“ active”(在此示例中为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',
    ));
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我的解决方案:

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