如何从表单内部访问服务和配置

3.4 版本
维护中的版本

有时,你需要从你的表单类里去访问一个服务或其他配置信息。要实现这个,有两种可能:

1) 传递选项到你的表单 

最简单的方式是,通过form options(表单选项)来传入服务或配置。假设你需要访问doctrine.orm.entity_manager服务,以便能够进行查询。首先,允许(实际上是“必须”)一个新的entity_manager选项传入到你的表单中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/AppBundle/Form/TaskType.php
// ...
 
class TaskType extends AbstractType
{
    // ...
 
    public function configureOptions(OptionsResolver $resolver)
    {
        // ...
 
        $resolver->setRequired('entity_manager');
    }
}

做完这个,在创建表单时,你必须 传入一个entity_manager选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
// src/AppBundle/Controller/DefaultController.php
use AppBundle\Form\TaskType;
 
// ...
public function newAction()
{
    $task = ...;
    $form = $this->createForm(TaskType::class, $task, array(
        'entity_manager' => $this->get('doctrine.orm.entity_manager')
    ));
 
    // ...
}

最后,entity_manager选项可以在buildForm方法中的$options参数中被访问到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/AppBundle/Form/TaskType.php
// ...
 
class TaskType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        /** @var \Doctrine\ORM\EntityManager $em */
        $em = $options['entity_manager'];
        // ...
    }
 
    // ...
}

使用这种方式可以把任何东西 传入到你的表单。

2) 把表单定义成服务 

另一种可能是,把你的表单类定义成服务。如果你希望在多处复用表单的话,这是个好办法——把它注册成服务可以令事情更简单。

假设你需要访问doctrine.orm.entity_manager服务以便能够查询。首先,把它作为参数添加到你的表单类中:

1
2
3
4
5
6
7
8
9
// src/AppBundle/Resources/config/services.php
$container
    ->register(
        'app.form.type.task',
        'AppBundle\Form\TaskType'
    )
    ->addArgument('@doctrine.orm.entity_manager')
    ->addTag('form.type')
;

接下来,注册表单类为服务,并打上form.type标签:

1
2
3
4
5
6
7
# src/AppBundle/Resources/config/services.yml
services:
    app.form.type.task:
        class: AppBundle\Form\TaskType
        arguments: ['@doctrine.orm.entity_manager']
        tags:
            - { name: form.type }
1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- src/AppBundle/Resources/config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
 
    <services>
        <service id="app.form.type.task" class="AppBundle\Form\TaskType">
            <argument type="service" id="doctrine.orm.entity_manager"/>
            <tag name="form.type" />
        </service>
    </services>
</container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// src/AppBundle/Form/TaskType.php
 
use Doctrine\ORM\EntityManager;
// ...
 
class TaskType extends AbstractType
{
    private $em;
 
    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }
 
    // ...
}

完成!在控制器中——也就是你创建表单的地方——什么也不需要动:Symfony足够智能地从服务容器中加载TaskType

参考把表单字段创建成一个服务以了解更多。

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)