symfony 2.3 form getData doesn't work in subforms collections

前端 未结 5 480
南方客
南方客 2021-01-31 23:04

I have a form which contains a collection. So I have:

/* my type */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
             


        
5条回答
  •  南旧
    南旧 (楼主)
    2021-02-01 00:00

    To understand what is happening here you have to understand data mapping first. When you call

    $form->setData(array('photoname' => 'Foobar', 'size' => 500));
    

    the form's data mapper is responsible for taking the given array (or object) and writing the nested values into the fields of the form, i.e. calling

    $form->get('photoname')->setData('Foobar');
    $form->get('size')->setData(500);
    

    But in your example, you are not dealing with Form, but with FormBuilder objects. FormBuilder is responsible for collecting the configuration of a form and using this information to produce a Form instance. As such, FormBuilder also lets you store the default data for the form. But since it's a simple configuration object only, it will not invoke the data mapper as of yet. For example:

    $builder = $factory->createBuilder()
        ->add('photoname')
        ->add('size')
        ->setData(array('photoname' => 'Foobar', 'size' => 500));
    
    print_r($builder->get('photoname')->getData());
    print_r($builder->get('size')->getData());
    

    This example will output:

    null
    null
    

    because data mapping takes place later, when we turn the FormBuilder into a Form instance. We can use this fact to set separate default values for the individual fields:

    $builder->add('size', null, array('data' => 100));
    // which is equivalent to
    $builder->get('size')
        ->setData(100)
        ->setDataLocked(true);
    
    print_r($builder->get('photoname')->getData());
    print_r($builder->get('size')->getData());
    

    And the output:

    null
    100    
    

    Data locking is required to prevent the data mapper from overriding the default data you just stored. This is done automatically if you pass the "data" option.

    At last, you will build the form. Now, FormBuilder calls Form::setData() where necessary, which in turn will invoke the data mapper:

    $form = $builder->getForm();
    
    // internally, the following methods are called:
    
    // 1) because of the default data configured for the "size" field
    $form->get('size')->setData(100);
    
    // 2) because of the default data configured for the main form
    $form->setData(array('photoname' => 'Foobar', 'size' => 500));
    
    // 2a) as a result of data mapping
    $form->get('photoname')->setData('Foobar');
    
    // 2b) as a result of data mapping (but ignored, because the data was locked)
    $form->get('size')->setData(500);
    

提交回复
热议问题