将自定义选项传递给symfony2表单

Thr*_*oze 26 forms symfony

在symfony 1.4中,可以通过表单的选项参数化表单类定义.有没有办法将自定义选项传递给我的自定义表单类型??? 我试图使用方法的options参数buildForm,但我不太清楚这个数组是什么,显然它不是我想要的...谢谢!

pul*_*der 43

解决方案很简单,如果您希望自定义选项也可以在Twig模板中使用,则必须$builder->setAttribute()buildForm方法中使用 方法和 $view->set()方法buildView().

<?php

namespace Acme\DemoBundle\Form\Type;

use Symfony\Component\Form\AbstractType as FormAbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;

// For Symfony 2.1 and higher:
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * ImagePreviewType
 *
 */
class ImagePreviewType extends FormAbstractType
{

    /**
     * {@inheritDoc}
     * For Symfony 2.0
     */
    //public function getDefaultOptions(array $options)
    //{
    //    $options = parent::getDefaultOptions($options);
    //    $options['base_path'] = 'path/to/default/dir/';
    //
    //    return $options;
    //}

    /**
     * {@inheritDoc}
     * For Symfony 2.1 and higher
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'base_path'         => '',
        ));
    }

    /**
     * {@inheritDoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        // For Symfony 2.0:
        // $view->set('base_path', $form->getAttribute('base_path'));

        // For Symfony 2.1 and higher:
        $view->vars['base_path'] = $options['base_path'];
    }

    /**
     * {@inheritDoc}
     */
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder
            ->setAttribute('base_path', $options['base_path'])
        ;
    }

    /**
     * {@inheritDoc}
     */
    public function getName()
    {
        return 'image_preview';
    }

    public function getParent(array $options)
    {
        // for Symfony 2.0:
        // return 'field';

        // for Symfony 2.1 and higher:
        return 'form';
    }
}
Run Code Online (Sandbox Code Playgroud)

自定义表单类型的模板(文件... Acme/DemoBundle/Resources/views/Form/fields.html.twig):

{% block image_preview_widget %}
{% spaceless %}
<img src="{{ base_path ~ value }}" alt=""  {{ block('widget_container_attributes') }} />
{% endspaceless %}
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

在app/config/config.yml中注册自定义表单类型的模板

twig:
    debug:            %kernel.debug%
    strict_variables: %kernel.debug%
    form:
        resources:
            - 'AcmeDemoAdminBundle:Form:fields.html.twig'
Run Code Online (Sandbox Code Playgroud)

用法:在编辑个人资料时显示用户图像的预览:

// src/Acme/DemoBundle/Form/Type/UserType.php
namespace Acme\DemoBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;

class UserType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder->add('user_profile_image_file_name', new ImagePreviewType(), array(
            'base_path' => 'some/other/dir',
        ));
    }
}
Run Code Online (Sandbox Code Playgroud)

2014-08-18:针对Symfony 2.1或更高版本进行了更新


eag*_*tor 18

更新:请注意,此解决方案仅适用于Symfony 2.0.x,它已过时,setDefaultOptions而不是使用getDefaultOptions.


公正地说,Symfony 2表单类型接受可以在表单类型中使用的任何选项.您需要覆盖getDefaultOptions方法以指定类型选项.

例如,我有一个MyCustomType接受的类型my_option,这个选项有一个默认值false,执行MyCustomType可以是这样的.

class MyCustomType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        if($options['my_option']){
            //do something
        } else {
            //do another thing
        }
        ...
    }

    public function getDefaultOptions(array $options)
    {
        return array(
            'my_option' => false
        );
    }

    public function getName()
    {
        return 'mycustomtype';
    }
}
Run Code Online (Sandbox Code Playgroud)

稍后,您需要在控制器中使用第三个参数创建表单时指定选项buildForm:

$form = $this->buildForm(new MyCustomType(), null, array(
    'my_option' => true
));
Run Code Online (Sandbox Code Playgroud)

如果未指定该my_option选项,则采用默认值(false).

  • 显然它不再是`getDefaultOptions()`了,而是使用`setDefaultOptions()`.否则它会说"选项"no_animal_type"不存在.已知选项包括:"action","attr","auto_initialize",......` (9认同)
  • 此解决方案支持您要使用的任何密钥,您只需覆盖`getDefaultOptions`方法即可. (4认同)

Eri*_*ldt 10

使用symfony 2.8,我成功地使用了扩展该configureOptions()方法的建议解决方案.

class ElementType extends AbstractType
{
    // ...

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'my_custom_option_parameter' => null,
        ));
    }
}
Run Code Online (Sandbox Code Playgroud)

我需要使用ElementType,作为集合和嵌入的表单.我意识到这是不可能通过my_custom_option_parameterCollectionType,因为我没有定制configureOptions()CollectionType,但我的ElementType.如果需要my_custom_option_parameter通过a CollectionType,则可以通过定义my_custom_option_parameterin entry_options(参见Documentation CollectionType Field)数组来成功CollectionType.

示例my_custom_option_parameter通过CollectionType:

class OuterFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    { 
        //...
        $builder->add('elements', CollectionType::class, array(
            'entry_type' => ElementType::class,
            // ...
            'entry_options' => array(
                'my_custom_option_parameter' => 'value is now set!'
            )
        ));
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)


Pio*_*ski 5

基于@pulzarraider 的回答,我创建了对 Symfony 3 进行更改的代码。

你需要改变

OptionsResolverInterface 为了 OptionsResolver

FormBuilder 为了 FormBuilderInterface

就我而言:

namespace MediaBundle\Form;

use Symfony\Component\Form\AbstractType as FormAbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;

class ImageType extends FormAbstractType {

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(array(
            'max_images' => ''
        ));
    }

    public function buildView(FormView $view, FormInterface $form, array $options) {

        $view->vars['max_images'] = $options['max_images'];
    }

    public function buildForm(FormBuilderInterface $builder, array $options) {

        $builder
                ->setAttribute('max_images', $options['max_images'])
        ;
    }

    public function getName() {
        return 'image_preview';
    }

    public function getParent() {
        return TextareaType::class;
    }
}
Run Code Online (Sandbox Code Playgroud)