如何使用 FormBuilder 将 "extra" 数据发送到 Symfony 3.2.x 表单?

How do I send "extra" data to a Symfony 3.2.x form using FormBuilder?

我在 Symfony 3.2.7 控制器中有以下方法:

public function updateAction(Request $request)
{
    $em        = $this->getDoctrine()->getManager();
    // this is the original entity without modified values
    $entity    = $em->getRepository('QuoteBundle:Quote')->find($request->query->get('id'));

    // the entity passed to the form has the values modified coming from the request    
    $form = $this->createForm(CFProgramLevelQuoteType::class, $entity);
    ...
}

这是表格:

class CFProgramLevelQuoteType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('CFProgramLevel', EntityType::class, [
                'class'         => 'QuoteBundle:CFProgramLevel',
                'choice_label'  => 'description',
                'placeholder'   => 'Please select a program',
            ]);
    }
    ...
}

我将使用查询生成器从 QuoteBundle:CFProgramLevel 中过滤一些值,因此我需要从 $entity 中获取未修改的 ID 并将其发送到表单。这是我目前想到的解决方案:

public function updateAction(Request $request)
{
    $em        = $this->getDoctrine()->getManager();
    $entity    = $em->getRepository('QuoteBundle:Quote')->find($request->query->get('id'));
    $entity_id = $entity->getCfProgramLevel()->getcfProgramLevelId();   
    $form = $this->createForm(CFProgramLevelQuoteType::class, $entity);
    ...
}

但是我如何将 entity_id 传递给表单并在那里使用它呢?如果有更好的方法来实现这一目标,我愿意听取想法。我在 Google 中找不到任何有用的信息,因此不胜感激。

更新

尝试了以下答案中提供的解决方案,我也无法正常工作:

// controller
$form = $this->createForm(CFProgramLevelQuoteType::class, $entity, ['entity_id' => $entity_id]);

// form
public function buildForm(FormBuilderInterface $builder, array $options)
{
    dump($options);
    die();
    ...
}

public function setDefaultOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(['data_class' => Quote::class, 'entity_id' => null]);
    $resolver->setRequired('entity_id');
}

The option "entity_id" does not exist. Defined options are: "action", "allow_extra_fields", "attr", "auto_initialize", "block_name", "by_reference", "compound", "constraints", "csrf_field_name", "csrf_message", "csrf_protection", "csrf_token_id", "csrf_token_manager", "data", "data_class", "disabled", "empty_data", "error_bubbling", "error_mapping", "extra_fields_message", "inherit_data", "invalid_message", "invalid_message_parameters", "label", "label_attr", "label_format", "mapped", "method", "post_max_size_message", "property_path", "required", "translation_domain", "trim", "upload_max_size_message", "validation_groups".

您可以按照 http://symfony.com/doc/current/form/create_custom_field_type.html#defining-the-field-type

中所述为表单类型创建自己的自定义选项
class CFProgramLevelQuoteType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        //$options['entity_id'] contains your id
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setRequired('entity_id');
    }
}

通过 entity_id:

$form = $this->createForm(CFProgramLevelQuoteType::class, $entity, [
    'entity_id' => $entity_id
]);

这是一个完整的示例(也与@striker 非常相似)。请仔细检查是否有任何拼写错误。否则尝试 php bin/console cache:clear

控制器动作:

public function testAction(Request $request)
{
    $form = $this->createForm(TestType::class, null, [
        'option1' => 6
    ]);
    return $this->render('default/test.html.twig',[
        'form' => $form->createView()
    ]);
}

TestType.php:

class TestType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('test', IntegerType::class, [
            'data' => $options['option1']
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setRequired('option1');
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_test';
    }
}

要将额外数据传递到表单,您可以使用 OptionsResolver::setDefined

// App\Form\SomeFormType
public function configureOptions(OptionsResolver $resolver): void
{
    $resolver->setDefined('foo');
}

您可以像这样在控制器中传递数据:

// Controller
$this->createForm(SomeFormType::class, $entity, ['foo' => $data]);

要使用传递的数据,只需访问定义的键:

// App\Form\SomeFormType
public function buildForm(FormBuilderInterface $builder, array $options): void
{
    // $options['foo']
}