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

问题描述 投票:131回答:22

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

php symfony
22个回答
99
投票

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

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

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

});

6
投票

不要使用:

'data' => 'Default value'

在这里阅读: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',
    ));
}

4
投票

我才明白这个问题。

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

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

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

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

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


4
投票

我的解决方案

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

4
投票

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

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

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

3
投票

通常,对于表单i的init默认值,使用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',
));

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

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

再见。


1
投票

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

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

1
投票

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

一个例子:

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

114
投票

您可以使用empty_data设置默认值

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

1
投票

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

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

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


1
投票

正如布莱恩问:

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

您可以使用empty_value设置默认值

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

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*/] );
        }
    });
}

62
投票

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

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

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

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这个并将所有数据设置为字段。在您的控制器中,您只需选择要激发的表单类型。如果你有一个自定义主题,并且喜欢事件,那就太糟糕了,为我的喜好创造了太多的维护。

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

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

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

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

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

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

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

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

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


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将始终设置为默认值,而不是从实体获取值。


19
投票

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

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

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


16
投票

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

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

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的答案进行调整。

请注意,这假定当属性是新的(而不是现有的)实体时,属性将仅具有值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'
        )
    );
}

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
投票

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

// 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'));
© www.soinside.com 2019 - 2024. All rights reserved.