6

在我的 Symfony2 项目中,我需要在数据库中生成现有表的列表。由于在我的项目中并不是所有的表都被用作实体,而且列表本身需要是一个简单的数组而不是一个实体,所以我为此编写了一个 sql 语句。此 sql 语句嵌入在自定义服务的函数中(并且已经过彻底测试)。

现在,在表单类型中,我想用上述函数的结果数组填充一个字段。这些成为用户可以选择的选项。

我的问题是如何以我的表单类型访问服务?

4

4 回答 4

16

有一个简单的解决方案,它是纯 OOP,没有特定于框架的配置。只需使用构造函数手动将您的服务实例注入您的表单类型实例:

class SomeType extends AbstractType
{
    private $provider;

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

    public function buildForm(FormBuilder $builder, array $options)
    {
         $builder->add('tables', 'choices', array(
             'choices' => $this->provider->getTableNames(),
         ));
    }
}

然后,在您的控制器中,例如:

public function newAction()
{
     $form = $this->createForm(new SomeType($this->get('table_name_provider'));

     // more stuff
}

完全一样可以使用框架配置来完成,遵循http://symfony.com/doc/2.0/cookbook/form/create_custom_field_type.html#creating-your-field-type-as-a-service

唯一的区别是它关心使用 DIC 实例化您的类型,并注入正确的依赖项。然后,您只需要修改您的控制器:

public function newAction()
{
     $form = $this->createForm('some_type_alias');

     // more stuff
}
于 2013-01-24T10:16:00.080 回答
7

表单类型的翻译服务访问示例:

您的表单类型类:

class TaskType extends AbstractType {
    ....
    public function setDefaultOptions(OptionsResolverInterface $resolver) {
        $resolver->setDefaults(array(
            't' => 'Symfony\Bundle\FrameworkBundle\Translation\Translator',
        ));
    }  

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $t = $options['t'];
        $t->trans('string to translate');
        ....
    }

控制器:

public function someAction() { 
    $form = $this->createForm(new TaskType(), 
                                $task, 
                                array('t' => $this->get('translator')));
于 2013-10-21T18:57:12.670 回答
3

Symfony 最佳实践

您还可以将表单类型注册为服务。仅当您的表单类型需要容器注入一些依赖项时才需要这样做,否则会产生不必要的开销,因此不建议对所有表单类型类执行此操作。

# src/AppBundle/Resources/config/services.yml
services:
    app.form.type.gender:
        class: AppBundle\Form\Type\ SomeType
        arguments:
            - "@app.table_name_provider"
        tags:
            - { name: form.type }
$form = $this->createForm(SomeType::class)
于 2016-08-26T16:27:09.137 回答
1

Symfony 3.X 的更新,您现在有两个选择...

通过选项发送服务

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

然后通过控制器传递

$form = $this->createForm(XXXType::class, $entity, array(
    'option_key' => $this->get('service_you_want_to_call')
));

将表单定义为服务

此选项更简洁 IMO,您不必在任何调用表单的地方发送选项

class XXXType extends AbstractType
{
    private $service;

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

然后在配置中定义服务

services:
    app.form.type.XXX:
        class: AppBundle\Form\XXXType
        arguments: ['@service_you_want_to_call']
        tags:
            - { name: form.type }

每次你用

$this->createForm(XXXType::class, $data, $options)

Symfony 将足够聪明,知道它必须使用该服务参数(它知道它是因为 form.type 标记),因此您不再需要将任何数据传递给构造函数。

Symfony 文档:如何从表单内部访问服务或配置

于 2017-04-21T10:54:29.780 回答