简体   繁体   English

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

[英]How to set default value for form field in Symfony2?

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

您可以使用empty_data设置默认值

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

Can be use during the creation easily with : 可以在创建过程中轻松使用:

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

I've contemplated this a few times in the past so thought I'd jot down the different ideas I've had / used. 我过去曾多次考虑过这一点,所以以为我记下了我曾经/曾经使用过的不同想法。 Something might be of use, but none are "perfect" Symfony2 solutions. 可能有用,但是没有一个是“完美的” Symfony2解决方案。

Constructor In the Entity you can do $this->setBar('default value'); 构造函数在Entity中,您可以执行$ this-> setBar('default value');。 but this is called every time you load the entity (db or not) and is a bit messy. 但这在每次加载实体(无论是否加载db)时都会调用,并且有点混乱。 It does however work for every field type as you can create dates or whatever else you need. 但是,它确实适用于每种字段类型,因为您可以创建日期或其他所需的内容。

If statements within get's I wouldn't, but you could. 如果其中的语句是“我不会”,但您可以。

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

Factory / instance . 工厂/实例 Call a static function / secondary class which provides you a default Entity pre-populated with data. 调用静态函数/辅助类,该类为您提供一个预先填充了数据的默认实体。 Eg 例如

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

   return $obj;
}

Not really ideal given you'll have to maintain this function if you add extra fields, but it does mean you're separating the data setters / default and that which is generated from the db. 如果添加额外的字段,您必须维护此功能,这并不是很理想,但这确实意味着您正在分隔数据设置器/默认值和从数据库生成的值。 Similarly you can have multiple getFactories should you want different defaulted data. 同样,如果要使用其他默认数据,则可以有多个getFactories。

Extended / Reflection entities Create a extending Entity (eg FooCreate extends Foo) which gives you the defaulted data at create time (through the constructor). 扩展/反射实体创建一个扩展实体(例如FooCreate扩展Foo),该实体在创建时(通过构造函数)为您提供默认数据。 Similar to the Factory / instance idea just a different approach - I prefer static methods personally. 与工厂/实例的想法类似,只是一种不同的方法-我个人更喜欢静态方法。

Set Data before build form In the constructors / service, you know if you have a new entity or if it was populated from the db. 在构建表单之前设置数据在构造函数/服务中,您知道是否有新实体,或者是否从数据库中填充了它。 It's plausible therefore to call set data on the different fields when you grab a new entity. 因此,当您获取一个新实体时,在不同的字段上调用集合数据是合理的。 Eg 例如

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

Form Events When you create the form you set default data when creating the fields. 表单事件创建表单时,在创建字段时设置默认数据。 You override this use PreSetData event listener. 您可以重写此使用PreSetData事件侦听器。 The problem with this is that you're duplicating the form workload / duplicating code and making it harder to maintain / understand. 这样做的问题是,您正在复制表单工作负载/复制代码,并使维护/理解变得更加困难。

Extended forms Similar to Form events, but you call the different type depending on if it's a db / new entity. 扩展的表单与Form事件类似,但是根据它是db / new实体还是调用不同的类型。 By this I mean you have FooType which defines your edit form, BarType extends FooType this and sets all the data to the fields. 我的意思是,您拥有定义编辑表单的FooType,BarType扩展了FooType,并将所有数据设置为字段。 In your controller you then simply choose which form type to instigate. 然后,您只需在控制器中选择要激发的表单类型即可。 This sucks if you have a custom theme though and like events, creates too much maintenance for my liking. 如果您有一个自定义主题(例如事件),这会很糟糕,但会给我带来太多的维护负担。

Twig You can create your own theme and default the data using the value option too when you do it on a per-field basis. 树枝您可以创建自己的主题,也可以在基于每个字段的情况下使用value选项将数据默认设置。 There is nothing stopping you wrapping this into a form theme either should you wish to keep your templates clean and the form reusable. 如果您希望保持模板干净并且可重用表单,那么没有什么可以阻止您将其包装到表单主题中的。 eg 例如

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

JS It'd be trivial to populate the form with a JS function if the fields are empty. JS如果字段为空,则用JS函数填充表单很简单。 You could do something with placeholders for example. 例如,您可以使用占位符。 This is a bad, bad idea though. 不过,这是一个坏主意。

Forms as a service For one of the big form based projects I did, I created a service which generated all the forms, did all the processing etc. This was because the forms were to be used across multiple controllers in multiple environments and whilst the forms were generated / handled in the same way, they were displayed / interacted with differently (eg error handling, redirections etc). 表单即服务对于我所做的基于大型表单的项目之一,我创建了一个服务,该服务生成所有表单,进行所有处理等。这是因为表单要在多个环境中的多个控制器之间使用,而表单以相同的方式生成/处理,它们以不同的方式显示/交互(例如错误处理,重定向等)。 The beauty of this approach was that you can default data, do everything you need, handle errors generically etc and it's all encapsulated in one place. 这种方法的优点在于,您可以默认数据,执行所需的所有操作,一般性地处理错误等,并且都封装在一个地方。

Conclusion As I see it, you'll run into the same issue time and time again - where is the defaulted data to live? 结论正如我所看到的,您会一次又一次遇到相同的问题-默认数据存放在哪里?

  • If you store it at db/doctrine level what happens if you don't want to store the default every time? 如果将其存储在db / doctrine级别,如果不想每次都存储默认值,会发生什么?
  • If you store it at Entity level what happens if you want to re-use that entity elsewhere without any data in it? 如果将其存储在实体级别,如果您想在其他地方重复使用该实体而又没有任何数据,会发生什么情况?
  • If you store it at Entity Level and add a new field, do you want the previous versions to have that default value upon editing? 如果将其存储在实体级别并添加新字段,是否要让以前的版本在编辑时具有该默认值? Same goes for the default in the DB... 数据库中的默认设置也是如此...
  • If you store it at the form level, is that obvious when you come to maintain the code later? 如果将其存储在表单级别,那么以后再维护代码时很明显吗?
  • If it's in the constructor what happens if you use the form in multiple places? 如果在构造函数中,如果您在多个地方使用表单会发生什么?
  • If you push it to JS level then you've gone too far - the data shouldn't be in the view never mind JS (and we're ignoring compatibility, rendering errors etc) 如果将其推向JS级别,则说明您已经走得太远了-数据不应该放在视图中,不用担心JS(而且我们忽略了兼容性,渲染错误等)
  • The service is great if like me you're using it in multiple places, but it's overkill for a simple add / edit form on one site... 如果像我一样在多个地方使用它,该服务将是很棒的选择,但是对于在一个站点上进行简单的添加/编辑表单来说,这太过分了...

To that end, I've approached the problem differently each time. 为此,我每次都以不同的方式处理该问题。 For example, a signup form "newsletter" option is easily (and logically) set in the constructor just before creating the form. 例如,在创建表单之前,可以轻松(逻辑上)在构造函数中设置注册表单的“新闻简报”选项。 When I was building forms collections which were linked together (eg which radio buttons in different form types linked together) then I've used Event Listeners. 当我建立链接在一起的表单集合(例如,不同表单类型的单选按钮链接在一起)时,我使用了事件监听器。 When I've built a more complicated entity (eg one which required children or lots of defaulted data) I've used a function (eg 'getFactory') to create it element as I need it. 当我建立了一个更复杂的实体(例如需要一个子代或大量默认数据的实体)时,我使用了一个函数(例如“ getFactory”)来根据需要创建它。

I don't think there is one "right" approach as every time I've had this requirement it's been slightly different. 我认为没有一种“正确”的方法,因为每次我有此要求时,它都会有所不同。

Good luck! 祝好运! I hope I've given you some food for thought at any rate and didn't ramble too much ;) 希望我能给您一点思考的东西,不要让您流连忘返;)

If you need to set default value and your form relates to the entity, then you should use following approach: 如果需要设置默认值,并且表单与实体相关,则应使用以下方法:

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

Otherwise, myField always will be set to default value, instead of getting value from entity. 否则, myField将始终设置为默认值,而不是从实体获取值。

You can set the default for related field in your model class (in mapping definition or set the value yourself). 您可以在模型类中为关联字段设置默认值(在映射定义中或自行设置值)。

Furthermore, FormBuilder gives you a chance to set initial values with setData() method. 此外,FormBuilder使您有机会使用setData()方法设置初始值。 Form builder is passed to the createForm() method of your form class. 表单构建器将传递到表单类的createForm()方法。

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

If your form is bound to an entity, just set the default value on the entity itself using the construct method: 如果您的表单绑定到实体,则只需使用Construct方法在实体本身上设置默认值:

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

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

Simply set the default value in your entity, either in the variable declaration or the constructor: 只需在变量声明或构造函数中为您的实体设置默认值即可:

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

or 要么

class Entity {
    private $color;

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

Approach 2 from a comment in the above link, and also Dmitriy's answer (not the accepted one) from How to set default value for form field in Symfony2? 上面链接中的注释中的方法2,以及如何在Symfony2中为表单字段设置默认值的 Dmitriy的答案(不是公认的答案)

Add the default value to the data attribute when adding the field with the FormBuilder, adapted from Dmitriy's answer. 在使用FormBuilder添加字段时,将默认值添加到data属性,该值根据Dmitriy的答案改编而成。

Note that this assumes that the property will and will only have the value null when it's a new, and not an existing, entity. 请注意,这假定该属性在成为新实体(而不是现有实体)时将并且将仅具有 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'
        )
    );
}

You can set a default value, eg for the form message , like this: 您可以为表单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();

In case your form is mapped to an Entity, you can go like this (eg default username): 如果您的表单已映射到实体,则可以这样进行操作(例如,默认用户名):

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

$form = $this->createFormBuilder($user)
    ->add('username')
    ->getForm();

A general solution for any case/approach, mainly by using a form without a class or when we need access to any services to set the default value: 对于任何情况/方法的通用解决方案,主要是通过使用不带类的表单或当我们需要访问任何服务来设置默认值时:

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

and register the form extension: 并注册表格扩展名:

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

After that, we can use default option in any form field: 之后,我们可以在任何表单字段中使用default选项:

$formBuilder->add('user', null, array('default' => $this->getUser()));
$formBuilder->add('foo', null, array('default' => 'bar'));
->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));
     }

});

Don't use: 不要使用:

'data' => 'Default value'

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

"The data option always overrides the value taken from the domain data (object) when rendering. This means the object value is also overriden when the form edits an already persisted object, causing it to lose its persisted value when the form is submitted." “数据选项在呈现时始终会覆盖从域数据(对象)获取的值。这意味着当表单编辑一个已保留的对象时,对象值也会被覆盖,从而在提交表单时会丢失其保留的值。”


Use the following: 使用以下内容:

Lets say, for this example, you have an Entity Foo, and there is a field "active" (in this example is CheckBoxType, but process is the same to every other type), which you want to be checked by default 可以说,在此示例中,您有一个Entity Foo,并且有一个字段“ active”(在此示例中为CheckBoxType,但是过程与其他所有类型相同),默认情况下您要对其进行检查

In your FooFormType class add: 在您的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',
    ));
}

Just so I understand the problem. 只是我了解问题所在。

You want to adjust the way the form is built based on data in your entity. 您要根据实体中的数据调整构建表单的方式。 If the entity is being created then use some default value. 如果正在创建实体,则使用一些默认值。 If the entity is existing use the database value. 如果实体存在,请使用数据库值。

Personally, I think @MolecularMans's solution is the way to go. 就个人而言,我认为@MolecularMans的解决方案是必经之路。 I would actually set the default values in the constructor or in the property statement. 我实际上将在构造函数或属性语句中设置默认值。 But you don't seem to like that approach. 但是您似乎不喜欢这种方法。

Instead you can follow this: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html 相反,您可以按照以下步骤操作: http : //symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

You hang a listener on your form type and you can then examine your entity and adjust the builder->add statements accordingly based on havine a new or existing entity. 您可以在表单类型上挂起一个侦听器,然后可以检查您的实体,并根据希望创建新实体或现有实体来相应地调整builder-> add语句。 You still need to specify your default values somewhere though you could just code them in your listener. 尽管您可以只在侦听器中对其进行编码,但仍需要在某个位置指定默认值。 Or pass them into the form type. 或将它们传递给表单类型。

Seems like a lot of work though. 似乎需要做很多工作。 Better to just pass the entity to the form with it's default values already set. 最好仅将实体传递给表单并设置其默认值。

My solution: 我的解决方案:

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

If you're using a FormBuilder in symfony 2.7 to generate the form, you can also pass the initial data to the createFormBuilder method of the Controler 如果您在symfony 2.7中使用FormBuilder生成表单,则还可以将初始数据传递到Controler的createFormBuilder方法

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

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

Often, for init default values of form i use fixtures. 通常,对于表单的初始默认值,我使用fixture。 Of cause this way is not easiest, but very comfortable. 当然,这种方式不是最简单的,但是非常舒适。

Example: 例:

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

Yet, symfony type field have the option data . 但是,symfony类型字段具有选项数据

Example

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

There is a very simple way, you can set defaults as here : 有一种非常简单的方法,您可以在此处设置默认值:

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

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

If you set 'data' in your creation form, this value will be not modified when edit your entity. 如果您在创建表单中设置“数据”,则在编辑实体时不会修改此值。

My solution is : 我的解决方案是:

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

Bye. 再见

Default values are set by configuring corresponding entity. 通过配置相应的实体来设置默认值。 Before binding the entity to form set its color field to "#0000FF": 在将实体绑定为表格之前,将其颜色字段设置为“#0000FF”:

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

If that field is bound to an entity (is a property of that entity) you can just set a default value for it. 如果该字段绑定到实体(该实体的属性),则可以为其设置默认值。

An example: 一个例子:

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

I usually just set the default value for specific field in my entity: 我通常只为实体中的特定字段设置默认值:

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

This will work for new records or if just updating existing ones. 这将适用于新记录或仅更新现有记录。

As Brian asked: 正如Brian所问:

empty_data appears to only set the field to 1 when it is submitted with no value. empty_data似乎仅在提交没有值的字段时将其设置为1。 What about when you want the form to default to displaying 1 in the input when no value is present? 如果您希望在不存在任何值的情况下让表单默认为在输入中显示1,该怎么办?

you can set the default value with empty_value 您可以使用empty_value设置默认值

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

I solve this problem like this in symfony 3.4 我在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*/] );
        }
    });
}

I solved this problem, by adding value in attr : 我通过在attr中添加解决了这个问题:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM