【问题标题】:Problems passing extra parameters to Symfony2 forms trough $options通过 $options 将额外参数传递给 Symfony2 表单的问题
【发布时间】:2014-12-30 22:32:37
【问题描述】:

我正在尝试为我在 Symfony 2.6.1 中的表单类型传递一个额外的选项,如下所示 (FabricanteForm.php):

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
            ->add('nombre', 'text')
            ->add('direccion', 'textarea')
            ->add('telefono', 'text', array(
                'required' => TRUE,
                'trim' => TRUE,
            ))
            ->add('fax', 'text', array(
                'required' => FALSE,
            ))
            ->add('correo', 'email', array(
                'required' => FALSE,
            ));

    if ($options['isFabricante'] !== null)
    {
        $builder->add('pais', 'text');
    }
    else
    {
        $builder->add('pais', 'entity', array(
            'class' => 'AppBundle:Pais',
            'property' => 'nombre',
            'query_builder' => function (EntityRepository $er) {
                return $er->createQueryBuilder('qb')
                          ->where('qb.activo = :activoValue')
                          ->setParameter('activoValue', true);
            },
            'mapped' => FALSE,
            'expanded' => FALSE,
            'multiple' => TRUE,
        ));
    }
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setOptional(array(
        'isFabricante',
    ));

    $resolver->setDefaults(array(
        'data_class' => 'Sencamer\AppBundle\Entity\FabricanteDistribuidor',
        'intention' => 'fabricante',
        'isFabricante' => null
    ));
}

然后我在控制器上创建表单如下:

$entityPais = new Entity\Pais();
$formPaisesDistribuidor = $this->createForm(new Form\PaisesForm(), $entityPais, array('isFabricante' => null));
$formPaisesFabricante = $this->createForm(new Form\PaisesForm(), $entityPais, array('isFabricante' => true));

但是我收到了这个错误:

The option "isFabricante" does not exist. Known options are: "action", "allow_extra_fields", "attr", "auto_initialize", "block_name", "by_reference", "cascade_validation", "compound", "constraints", "csrf_field_name", "csrf_message", "csrf_protection", "csrf_provider", "csrf_token_id", "csrf_token_manager", "data", "data_class", "disabled", "empty_data", "error_bubbling", "error_mapping", "extra_fields_message", "inherit_data", "intention", "invalid_message", "invalid_message_parameters", "label", "label_attr", "label_format", "mapped", "max_length", "method", "pattern", "post_max_size_message", "property_path", "read_only", "required", "translation_domain", "trim", "validation_groups", "virtual".

这是在表单类型上设置额外参数的正确方法吗?这是重用表单的最佳方式吗? (您可能注意到$formPaisesDistribuidor$formPaisesFabricante 之间的唯一区别是pais 字段类型,第一个是实体,第二个是文本)

有什么帮助吗?建议?

【问题讨论】:

  • 如您所见,每种表单类型都有一个特定的选项列表。将参数作为构造函数参数传递是最简单的。
  • @Cerad 奇怪的部分,除非在 2.6.x 上有所改变,否则我在 2.5.x 项目中使用相同的方法。无论如何,我只是尝试一下您的建议,谢谢
  • 有趣的是 2.5。我在 2.0 或 2.1 的时候遇到过这个问题。
  • 您的方法在 2.6 中应该仍然有效,我只是使用您的方法在我的一个表单上对其进行了测试。
  • @ReynierPM 你应该把这个条件移到symfony.com/doc/current/cookbook/form/…

标签: php symfony symfony-forms


【解决方案1】:

引用 Turdaliev 关于 $options 没有被用于他想要的东西的观点 - 我不同意,你绝对可以使用它。 Symfony 的文档显示了这两种方式。

这是一个将实体管理器传递给选项数组的 Symfony 示例:

http://symfony.com/doc/current/cookbook/form/data_transformers.html#using-the-transformer

这是另一个将选择传递给构造函数的 Symfony 示例:

http://symfony.com/doc/current/cookbook/form/create_custom_field_type.html#creating-your-field-type-as-a-service

Symfony Forms Best Practices,他们并没有告诉你首选哪种方法,所以你可以自己决定。

我喜欢将$options 数组用于简单的布尔标志...因为它们 选项。另外,如果您有几个字段,其中一些是可选的,一些是必需的,则不必弄乱构造函数参数的顺序。

至于您收到错误的原因,我不完全确定。在 Symfony 2.6 中,setOptional() 现在是 setDefined()。您仍然可以使用旧功能,但它已被弃用,并将在 3.0 中删除。此外,如果您只传递一个选项,则不再需要传递数组。你也不必在setDefaultOptions()中设置它

试试这个:

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefined('isFabricante');

    $resolver->setDefaults(array(
        'data_class' => 'Sencamer\AppBundle\Entity\FabricanteDistribuidor',
        'intention'  => 'fabricante',
    ));
}

【讨论】:

  • 我正在查看从 2.5.x 到 2.6.x 的 UPGRADE 文件,我注意到它也已将 OptionsResolverInterface 更改为 OptionsResolver 所以我对此的怀疑是过去我声明 use ...\OptionsResolverInterface现在我应该声明use ...\OptionsResolver,这是正确的方式?
  • 我刚刚查看了 Symfony 的 AbstractType,它仍然使用 OptionsResolverInterface,所以对于 Forms,您仍然可以将其保留为界面而不是 OptionsResolver
【解决方案2】:

正如您从异常中看到的,$options 参数不用于您的用途。因此,您可以为 FabricanteForm 类创建自定义构造函数,而不是将自定义选项传递给 Symfony 的标准 $options 参数。以下是如何完成所有这些事情的演示:

PraisesType

namespace School\CoreBundle\Form\Type;


use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class PraisesType extends AbstractType
{

private $options;

public function __construct($options)
{
    $this->options = $options;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
        $builder
            ->add('nombre', 'text')
            ->add('direccion', 'textarea')
            ->add('telefono', 'text', array(
            'required' => TRUE,
                'trim' => TRUE,
            ))
            ->add('fax', 'text', array(
                'required' => FALSE,
            ))
            ->add('correo', 'email', array(
                'required' => FALSE,
            ));

        if ($this->options['isFabricante'] !== null)
        {
            $builder->add('pais', 'text');
        }
        else
        {
            $builder->add('pais', 'entity', array(
                'class' => 'AppBundle:Pais',
                'property' => 'nombre',
                'query_builder' => function (EntityRepository $er) {
                    return $er->createQueryBuilder('qb')
                        ->where('qb.activo = :activoValue')
                        ->setParameter('activoValue', true);
                },
                'mapped' => FALSE,
                'expanded' => FALSE,
                'multiple' => TRUE,
            ));
        }
    }


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

用法

    $entityPais = new Entity\Pais();
    $formPaisesDistribuidor = $this->createForm(new Form\PaisesType(array('isFabricante' => null)), $entityPais);
    $formPaisesFabricante = $this->createForm(new Form\PaisesType(array('isFabricante' => true)), $entityPais);

【讨论】:

    猜你喜欢
    • 2018-09-27
    • 2017-12-18
    • 2018-10-07
    • 1970-01-01
    相关资源
    最近更新 更多