首页 文章

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

提问于
浏览
128

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

21 回答

  • 11

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

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

    你可以用 empty_data 设置默认值

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

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

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

    If statements within get's 我不会,但你可以 .

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

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

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

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

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

    Set Data before build form 在构造函数/服务中,您知道是否有新实体或者是否从数据库中填充了实体 . 因此,当您获取新实体时,在不同字段上调用设置数据是合理的 . 例如 .

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

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

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

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

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

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

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

    Conclusion 正如我所看到的,你会一次又一次地遇到同样的问题 - 默认数据存在于哪里?

    • 如果将其存储在db / doctrine级别,如果您不想每次都存储默认值,会发生什么?

    • 如果您将其存储在实体级别,如果您想在其他地方重新使用该实体而没有任何数据,会发生什么?

    • 如果将其存储在实体级别并添加新字段,是否希望以前的版本在编辑时具有该默认值?同样适用于DB中的默认值...

    • 如果将它存储在表单级别,那么在以后维护代码时这是否显而易见?

    • 如果它在构造函数中,如果您在多个位置使用该表单会发生什么?

    • 如果你把它推到JS级别那么你在视图中就不用担心JS(我们忽略了兼容性,渲染错误等)

    • 如果像我一样,这项服务很棒're using it in multiple places, but it'在一个网站上为一个简单的添加/编辑表单而言太过分了......

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

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

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

  • 4

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

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

  • 16

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

    此外,FormBuilder为您提供了使用setData()方法设置初始值的机会 . 表单构建器将传递给表单类的createForm()方法 .

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

  • 9

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

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

    方法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的答案进行调整 .

    请注意,这假定属性 will and will only have 在为新实体而非现有实体时为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'
            )
        );
    }
    
  • 59

    您可以设置默认值,例如对于表单 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();
    
  • 6

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

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

    我才明白这个问题 .

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

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

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

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

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

  • 19

    我的解决方案

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

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

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

    Don't use:

    'data' => 'Default value'
    

    在这里阅读: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."


    使用以下内容:

    可以说,对于此示例,您有一个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())) $data->setActive(true);
            }
       );
    }
    public function configureOptions( OptionsResolver $resolver )
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle:Foo',
        ));
    }
    
  • 9

    通常,对于表单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',
    ));
    
  • 104

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

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

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

    我的解决方案是:

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

    再见 .

  • 2

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

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

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

    一个例子:

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

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

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

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

  • 3

    正如布莱恩问:

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

    你可以用 empty_value 设置默认值

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

相关问题