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

时间:2011-10-27 07:56:54

标签: php symfony

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

23 个答案:

答案 0 :(得分:114)

您可以使用empty_data

设置默认值
$builder->add('myField', 'number', ['empty_data' => 'Default value'])

答案 1 :(得分:100)

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

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

答案 2 :(得分:61)

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

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

如果在get&#39>中的陈述 我不会,但你可以。

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

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

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

   return $obj;
}

如果您添加了额外的字段,那么您不得不维护此功能,但这确实意味着您要分离数据设置器/默认值以及从数据库生成的数据。同样,如果您需要不同的默认数据,您可以拥有多个getFactories。

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

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

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

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

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

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

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

<强> JS 如果字段为空,使用JS函数填充表单是微不足道的。例如,您可以使用占位符执行某些操作。但这是一个糟糕的坏主意。

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

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

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

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

我不认为有一个&#34;对&#34;每当我有这个要求时它就会有所不同。

祝你好运!我希望无论如何我都能给你一些思考的食物并且不会絮絮叨叨;)

答案 3 :(得分: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'
        )
    );
}

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

答案 4 :(得分:19)

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

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

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

答案 5 :(得分:16)

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

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

答案 6 :(得分:12)

方法1(来自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添加字段时,将默认值添加到数据属性,改编自Dmitriy的答案。

请注意,这假设属性只有当它是新的而不是现有的实体时。

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

答案 7 :(得分: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;
    }
}

并注册表单扩展名:

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

答案 8 :(得分: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();

答案 9 :(得分:6)

不要使用:

'data' => 'Default value'

请在此处阅读:https://symfony.com/doc/current/reference/forms/types/form.html#data

&#34;数据选项始终覆盖渲染时从域数据(对象)获取的值。这意味着当表单编辑已经存在的对象时,对象值也会被覆盖,导致它在提交表单时丢失其持久值。&#34;

使用以下内容:

让我们说,对于这个例子,你有一个实体Foo,并且有一个字段&#34; active&#34; (在此示例中为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',
    ));
}

答案 10 :(得分: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));
     }

});

答案 11 :(得分:4)

我的解决方案:

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

答案 12 :(得分:4)

我理解这个问题。

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

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

相反,您可以遵循:http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

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

看起来好像很多工作。最好将实体传递给表单,并且已经设置了默认值。

答案 13 :(得分:4)

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

$values = array(
    'name' => "Bob"
);

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

答案 14 :(得分:3)

通常,对于表单的初始默认值,我使用fixture。因为这种方式不是最简单,但非常舒适。

示例:

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

答案 15 :(得分:3)

有一种非常简单的方法,您可以将默认值设置为:

$defaults = array('sortby' => $sortby,'category' => $category,'page' => 1);

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

答案 16 :(得分:2)

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

我的解决方案是:

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

再见。

答案 17 :(得分:1)

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

一个例子:

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

答案 18 :(得分:1)

布莱恩问道:

  

empty_data似乎只在没有值的情况下将字段设置为1。   当你希望表单默认在显示1时,怎么办?   没有值时输入?

您可以使用empty_value

设置默认值
$builder->add('myField', 'number', ['empty_value' => 'Default value'])

答案 19 :(得分:1)

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

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

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

答案 20 :(得分:1)

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

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

答案 21 :(得分:0)

我在symfony 3.4中解决了这个问题

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('field');

    $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $e) {
        if (!$e->getData()) {
            // in create new mode
            $e->getForm()
                ->add('field', NumberType::class, ['data' => 0 /*Default value here*/] );
        }
    });
}

答案 22 :(得分:0)

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

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