Dependency Injection Tags(注入之标签)

3.3 版本
维护中的版本

依赖注入(所用到)的标签(tag)是一个小字符串,可用作服务的“旗标(flag)”,以标记服务应当以某种特殊方式来使用。例如,如果你有一个服务,你希望把它注册为监听(listner),用于Symfony的核心事件,你可以把这个监听用 kernel.event_listener 标签进行标记。

通过服务容器大章的 如何操作服务的标签 一文,你可以了解更多关于“tag”的内容。

下面是Symfony全部可用的标签信息。你所使用bundle中的某些标签可能不在此列。

Tag Name / 标签名称 Usage / 作用
assetic.asset 对当前asset manager注册一个asset
assetic.factory_worker 添加一个factory worker
assetic.filter 注册一个filter
assetic.formula_loader 对当前asset manager添加一个formula loader
assetic.formula_resource 对当前asset manager添加一个resource
assetic.templating.php 如果PHP templating被禁用,则删除此服务
assetic.templating.twig 如果Twig templating被禁用,则删除此服务
auto_alias 基于容器参数的值来定义假名
console.command 添加一个命令
controller.argument_value_resolver 对诸如 Request 这种控制器参数注册一个value resolver
data_collector 创建一个类,用于收集profiler分析器的自定义数据
doctrine.event_listener 添加一个Doctrine event listener
doctrine.event_subscriber 添加一个Doctrine event subscriber
form.type 创建一个自定义的表单字段类型
form.type_extension 创建一个自定义的"form extension"表单扩展
form.type_guesser 对"form type guessing"(表单类型猜测)添加你自己的逻辑
kernel.cache_clearer 注册你的服务,在清除缓存的进程中会被调用
kernel.cache_warmer 注册你的服务,在缓存warming的进程中会被调用
kernel.event_listener 在Symfony中监听不同的事件/勾子(hooks)
kernel.event_subscriber 在Symfony中订阅一组不同的事件/勾子(hooks)
kernel.fragment_renderer 添加一个新的HTTP内容渲染策略
monolog.logger 在自定义的logging channel中做日志
monolog.processor 为logging添加一个自定义的processor
routing.loader 注册一个自定义的服务用于加载路由
routing.expression_language_provider 注册一个provider,用于路由中的表达式语言
security.expression_language_provider 注册一个provider,用于security中的表达式语言
security.voter 为Symfony的authorization逻辑添加一个自定义voter
security.remember_me_aware 允许remember me(记住我)的authentication方式
serializer.encoder serializer 服务中注册一个新的encoder
serializer.normalizer serializer 服务中注册一个新的normalizer
swiftmailer.default.plugin 注册一个自定义的SwiftMailer插件
templating.helper 令你的服务能够在PHP templates中使用
translation.loader 注册一个自定义的服务用于加载翻译组件
translation.extractor 注册一个自定义的服务,用于从一个文件中提取翻译信息
translation.dumper 注册一个自定义的服务用于剥离翻译信息
twig.extension 注册一个自定义的Twig扩展
twig.loader 注册一个自定义的服务用于加载Twig模板
validator.constraint_validator 创建你自己的自定义validation约束
validator.initializer 注册一个自定义的服务,用于在验证开始之前初始化对象

assetic.asset 

作用: 对当前asset manager注册一个asset

assetic.factory_worker 

作用: 添加一个factory worker

Factory worker(工厂工人),是一个实现了 Assetic\Factory\Worker\WorkerInterface 接口的类。它的 process($asset) 方法在每一个asset创建之后被调用。你可以修改一个资源,甚至返回一个新的。

为了添加新工人,首先创建一个类:

1
2
3
4
5
6
7
8
9
10
11
use Assetic\Asset\AssetInterface;
use Assetic\Factory\Worker\WorkerInterface;
 
class MyWorker implements WorkerInterface
{
    public function process(AssetInterface $asset)
    {
        // ... change $asset or return a new one / 改变$asset或返回一个新的
    }
 
}

然后将其注册成服务并打上标签:

1
2
3
4
5
services:
    acme.my_worker:
        class: MyWorker
        tags:
            - { name: assetic.factory_worker }
1
2
3
4
5
6
7
8
9
10
11
<?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="acme.my_worker" class="MyWorker">
            <tag name="assetic.factory_worker" />
        </service>
    </services>
</container>
1
2
3
4
$container
    ->register('acme.my_worker', 'MyWorker')
    ->addTag('assetic.factory_worker')
;

assetic.filter 

作用: 注册一个filter

AsseticBundle使用此标签来注册普通的filters(过滤器)。你可以使用这个标签来注册你自己的过滤器。

首先,创建一个过滤器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
use Assetic\Asset\AssetInterface;
use Assetic\Filter\FilterInterface;
 
class MyFilter implements FilterInterface
{
    public function filterLoad(AssetInterface $asset)
    {
        $asset->setContent('alert("yo");' . $asset->getContent());
    }
 
    public function filterDump(AssetInterface $asset)
    {
        // ...
    }
}

第二步,定义一个服务:

1
2
3
4
5
services:
    acme.my_filter:
        class: MyFilter
        tags:
            - { name: assetic.filter, alias: my_filter }
1
2
3
4
5
6
7
8
9
10
11
<?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="acme.my_filter" class="MyFilter">
            <tag name="assetic.filter" alias="my_filter" />
        </service>
    </services>
</container>
1
2
3
4
$container
    ->register('acme.my_filter', 'MyFilter')
    ->addTag('assetic.filter', array('alias' => 'my_filter'))
;

最后,应用此过滤器:

1
2
3
4
5
6
{% javascripts
    '@AcmeBaseBundle/Resources/public/js/global.js'
    filter='my_filter'
%}
    <script src="{{ asset_url }}"></script>
{% endjavascripts %}

你可以通过 assetic.filters.my_filter.apply_to 配置选项来应用你自己的过滤器,就像下文描述的:如何对一个特定的文件扩展应用Assetic过滤器 。照做时,你必须定义在一个独立的xml配置文件中定义你的过滤器service,将它通过 assetic.filters.my_filter.resource 配置键指向该文件的路径。

assetic.formula_loader 

作用: 对当前asset manager添加一个formula loader

Formula loader(公式化内容加载器)是一个实现了 Assetic\Factory\Loader\FormulaLoaderInterface 接口的类。这个类负责的是,从一个特定种类的resource(比如,twig模板)中,来加载assets资源。Assetic自带了用于PHP和Twig两种模板的loader。

标签的 alias 属性,定义的是加载器的名字。

assetic.formula_resource 

作用: 对当前asset manager添加一个resource

resource(资源)指的是,能对loader提供“fomulae”(公式化内容)的东西。例如,许多Twig模板,就是resources。

assetic.templating.php 

作用: 如果PHP templating被禁用,则删除此服务

打了这个标签的服务会从容器中被删除,如果在 framework.templating.engines 配置区块中没有包含 php 模板引擎的话。

assetic.tempating.twig 

作用: 如果Twig templating被禁用,则删除此服务

打了这个标签的服务会从容器中被删除,如果在 framework.templating.engines 配置区块中没有包含 twig 的话。

auto_alias 

作用: 基于容器参数的值来定义假名

思考下面这个定义了三个“不同但却相关”的服务的配置信息:

1
2
3
4
5
6
7
8
9
10
services:
    app.mysql_lock:
        class: AppBundle\Lock\MysqlLock
        public: false
    app.postgresql_lock:
        class: AppBundle\Lock\PostgresqlLock
        public: false
    app.sqlite_lock:
        class: AppBundle\Lock\SqliteLock
        public: false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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.mysql_lock" public="false"
                 class="AppBundle\Lock\MysqlLock" />
        <service id="app.postgresql_lock" public="false"
                 class="AppBundle\Lock\PostgresqlLock" />
        <service id="app.sqlite_lock" public="false"
                 class="AppBundle\Lock\SqliteLock" />
    </services>
</container>
1
2
3
4
5
$container
    ->register('app.mysql_lock', 'AppBundle\Lock\MysqlLock')->setPublic(false)
    ->register('app.postgresql_lock', 'AppBundle\Lock\PostgresqlLock')->setPublic(false)
    ->register('app.sqlite_lock', 'AppBundle\Lock\SqliteLock')->setPublic(false)
;

毋须同时处理这三个服务,你的程序只需一个通用的 app.lock 服务来作为这“三个服务中的某一个”的假名(alias),而这取决于某些配置选项。多亏了 auto_alias 选项,你可以自动创建这个“基于配置参数的取值”的假名。

假设存在一个 database_type 配置参数(configuration parameter)。那么,这个通用的 app.lock 服务,可以像下面这样去定义:

1
2
3
4
5
6
7
8
9
10
services:
    app.mysql_lock:
        # ...
    app.postgresql_lock:
        # ...
    app.sqlite_lock:
        # ...
    app.lock:
        tags:
            - { name: auto_alias, format: "app.%database_type%_lock" }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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.mysql_lock" public="false"
                 class="AppBundle\Lock\MysqlLock" />
        <service id="app.postgresql_lock" public="false"
                 class="AppBundle\Lock\PostgresqlLock" />
        <service id="app.sqlite_lock" public="false"
                 class="AppBundle\Lock\SqliteLock" />
 
        <service id="app.lock">
            <tag name="auto_alias" format="app.%database_type%_lock" />
        </service>
    </services>
</container>
1
2
3
4
5
6
7
8
$container
    ->register('app.mysql_lock', 'AppBundle\Lock\MysqlLock')->setPublic(false)
    ->register('app.postgresql_lock', 'AppBundle\Lock\PostgresqlLock')->setPublic(false)
    ->register('app.sqlite_lock', 'AppBundle\Lock\SqliteLock')->setPublic(false)
 
    ->register('app.lock')
    ->addTag('auto_alias', array('format' => 'app.%database_type%_lock'))
;

format 选项定义的是一个表达式,用于把服务名构造到假名中。这个表达式可以使用任意的容器参数(通常都是用 % 字符来引用参数名称)。

当使用 auto_alias 标签后,把这些“使用了假名”的服务定义为private(私有)并非强制要求。但是,这么做(比如在上例中)在许多时候是有意义的,可以防止直接访问这些服务,取而代之的是使用那个“通用服务”的假名。

console.command 

作用: 添加一个命令

关于在容器中注册你自己的命令(commands)之详细内容请参考如何把命令定义成服务一文。

controller.argument_value_resolver 

3.1 controller.argument_value_resolver 标签从Symfony 3.1开始被引入。

作用: 对诸如 Request 这种控制器参数注册一个value resolver

参数值解析器(value resolver)实现的是 ArgumentValueResolverInterface 接口,用于解析控制器参数的值,在这里进行了解释:扩展对Action参数的解析

data_collector 

作用: 创建一个类,用于收集profiler分析器的自定义数据

要了解创建自定义data collector的细节,阅读 如何创建自定义数据集器 一文。

doctrine.event_listener 

作用: 添加一个Doctrine event listener

要了解创建Doctrine事件监听的细节,阅读 如何注册事件监听和订阅器 一文。

doctrine.event_subscriber 

作用: 添加一个Doctrine event subscriber

要了解创建Doctrine事件订阅的细节,阅读 如何注册事件监听和订阅器 一文。

form.type 

作用: 创建一个自定义的表单字段类型

要了解创建自定义表单类型的细节,阅读 如何去创建一个自定义的表单字段类型 一文。

form.type_extension 

作用: 创建一个自定义的"form extension"表单扩展

要了解创建表单类型扩展的细节,阅读 如何去创建一个自定义的表单字段类型 一文。

form.type_guesser 

作用: 对"form type guessing"(表单类型猜测)添加你自己的逻辑

这个标签让你把自己的逻辑添加到 form guessing 进程中。默认时,表单猜测是由基于“validation metadata和Doctrine metadata”的猜测器(guessers)完成的。(如果你用的是Propel,则是Propel metadata)

关于创建你自己的type guesser的更多信息,参考 创建自定义的类型猜测器

kernel.cache_clearer 

作用: 注册你的服务,在清除缓存的进程中会被调用

只要你调用 cache:clear 命令,缓存清理就会发生。如果你的bundles缓存了文件,你应该在清理进程中,为它们添加自定义的缓存清理器。

为了注册你的自定义cache clearer,你必须先创建一个服务类:

1
2
3
4
5
6
7
8
9
10
11
12
13
// src/Acme/MainBundle/Cache/MyClearer.php
namespace Acme\MainBundle\Cache;
 
use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
 
class MyClearer implements CacheClearerInterface
{
    public function clear($cacheDir)
    {
        // clear your cache / 清除缓存
    }
 
}

然后注册此类为服务并打上 kernel.cache_clearer 标签:

1
2
3
4
5
services:
    my_cache_clearer:
        class: Acme\MainBundle\Cache\MyClearer
        tags:
            - { name: kernel.cache_clearer }
1
2
3
4
5
6
7
8
9
10
11
<?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="my_cache_clearer" class="Acme\MainBundle\Cache\MyClearer">
            <tag name="kernel.cache_clearer" />
        </service>
    </services>
</container>
1
2
3
4
$container
    ->register('my_cache_clearer', 'Acme\MainBundle\Cache\MyClearer')
    ->addTag('kernel.cache_clearer')
;

kernel.cache_warmer 

作用: 注册你的服务,在缓存warming的进程中会被调用

只要你执行 cache:warmupcache:clear 命令(除非你传入 --no-warmup 选项给 cache:clear ),缓存预热就会发生。如果上述命令之一未有运行,它也可能发生在处理请求时。它的目的是,对程序所需的缓存进行初始化,防止第一个用户出现任何重大的“cache hit”以免缓存被动态地生成。

要注册你自己的cache warmer,先得注册一个实现 CacheWarmerInterface 接口的服务类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/Acme/MainBundle/Cache/MyCustomWarmer.php
namespace Acme\MainBundle\Cache;
 
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
 
class MyCustomWarmer implements CacheWarmerInterface
{
    public function warmUp($cacheDir)
    {
        // ... do some sort of operations to "warm" your cache
        // ... 进行一些操作来“预热”你的缓存
    }
 
    public function isOptional()
    {
        return true;
    }
}

如果能在“毋须调用这个cache warmer”的时候来运行程序,那么 isOptional 方法应该返回true。在Symfony中,可选的预热器总是被默认执行(你可以改变此行为,在执行命令时添加 --no-optional-warmers 选项即可)。

在Symfony中注册你的warmer,打上 kernel.cache_warmer 标签:

1
2
3
4
5
services:
    main.warmer.my_custom_warmer:
        class: Acme\MainBundle\Cache\MyCustomWarmer
        tags:
            - { name: kernel.cache_warmer, priority: 0 }
1
2
3
4
5
6
7
8
9
10
11
12
13
<?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="main.warmer.my_custom_warmer"
            class="Acme\MainBundle\Cache\MyCustomWarmer"
        >
            <tag name="kernel.cache_warmer" priority="0" />
        </service>
    </services>
</container>
1
2
3
4
$container
    ->register('main.warmer.my_custom_warmer', 'Acme\MainBundle\Cache\MyCustomWarmer')
    ->addTag('kernel.cache_warmer', array('priority' => 0))
;

priority 值是可选的,默认是0。愈高的优先级,愈早被执行。

如果你的cache warmer因为任何异常而未能正常执行,在接下来的请求中Symfony不再二次执行。所以,你的程序和/或bundles应该在“被cache warmer生成的内容尚不可用”时,准备就绪。

Core Cache Warmers 

Cache Warmer Class Name / 类名 Priority / 优先级
TemplatePathsCacheWarmer 20
RouterCacheWarmer 0
TemplateCacheCacheWarmer 0

kernel.event_listener 

作用: 在Symfony中监听不同的事件/勾子(hooks)

在Symfony程序的执行过程中,不同的事件将被触发,你可以派遣一些事件。这个标签允许你把自己的类打入(hook) 到那些事件中。

关于监听的完整示例,参考 事件和事件监听一文。

Core Event Listener Reference 

要了解“与kernel中的每一个事件相关联”的监听参考,阅读 Symfony事件参考

kernel.event_subscriber 

作用: 在Symfony中订阅一组不同的事件/勾子(hooks)

要开启一个自定义的订阅,把它作为常规服务添加到你的配置文件中,然后打上 kernel.event_subscriber 标签:

1
2
3
4
5
services:
    kernel.subscriber.your_subscriber_name:
        class: Fully\Qualified\Subscriber\Class\Name
        tags:
            - { name: kernel.event_subscriber }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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="kernel.subscriber.your_subscriber_name"
            class="Fully\Qualified\Subscriber\Class\Name">
 
            <tag name="kernel.event_subscriber" />
        </service>
    </services>
</container>
1
2
3
4
5
6
7
$container
    ->register(
        'kernel.subscriber.your_subscriber_name',
        'Fully\Qualified\Subscriber\Class\Name'
    )
    ->addTag('kernel.event_subscriber')
;

你的订阅器服务,必须实现 EventSubscriberInterface接口。

如果你的服务是由工厂(factory)创建,你必须正确地设置此标签的 class 参数方可正确作动。

kernel.fragment_renderer 

作用: 添加一个新的HTTP内容渲染策略

要添加一个新的渲染策略 - 除了像是 EsiFragmentRenderer 这种核心策略的 - 创建一个实现 FragmentRendererInterface 接口的类,把它注册为服务,然后打上 kernel.fragment_renderer 标签。

monolog.logger 

作用: 在自定义的logging channel中做日志

Monolog允许你在若干日志频道(logging channels)共享它的handler。logger服务使用了名为 app 的频道,但当你把logger注入到一个服务中时,可以改变这个频道。

1
2
3
4
5
6
services:
    my_service:
        class: Fully\Qualified\Loader\Class\Name
        arguments: ['@logger']
        tags:
            - { name: monolog.logger, channel: acme }
1
2
3
4
5
6
7
8
9
10
11
12
<?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="my_service" class="Fully\Qualified\Loader\Class\Name">
            <argument type="service" id="logger" />
            <tag name="monolog.logger" channel="acme" />
        </service>
    </services>
</container>
1
2
3
4
5
$definition = new Definition('Fully\Qualified\Loader\Class\Name', array(
    new Reference('logger'),
));
$definition->addTag('monolog.logger', array('channel' => 'acme'));
$container->setDefinition('my_service', $definition);

你也可以在配置文件中设置自定义频道,然后从服务容器中直接取出相应的服务(参考 配置附加Channels而毋须给服务打标签)。

monolog.processor 

作用: 为logging添加一个自定义的processor

Monolog允许你在logger中或handler中添加处理器(processors),以便在日志中添加附加内容。处理器接收日志记录(record)作为其参数,同时必须在“向记录的 extra 属性中添加额外内容”之后返回它。

内置的 IntrospectionProcessor 可用于添加文件、代码行、类以及方法,以令logger触发:

你可以全局地添加一个处理器:

1
2
3
4
5
services:
    my_service:
        class: Monolog\Processor\IntrospectionProcessor
        tags:
            - { name: monolog.processor }
1
2
3
4
5
6
7
8
9
10
11
<?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="my_service" class="Monolog\Processor\IntrospectionProcessor">
            <tag name="monolog.processor" />
        </service>
    </services>
</container>
1
2
3
4
$container
    ->register('my_service', 'Monolog\Processor\IntrospectionProcessor')
    ->addTag('monolog.processor')
;

如果你的服务不是一个回调(即,没有使用 __invoke() ),你可以在tag中添加 method 属性,即可使用特殊(魔术)方法。

你也可以为一个特定的handler添加一颗处理器,使用 handler 属性即可:

1
2
3
4
5
services:
    my_service:
        class: Monolog\Processor\IntrospectionProcessor
        tags:
            - { name: monolog.processor, handler: firephp }
1
2
3
4
5
6
7
8
9
10
11
<?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="my_service" class="Monolog\Processor\IntrospectionProcessor">
            <tag name="monolog.processor" handler="firephp" />
        </service>
    </services>
</container>
1
2
3
4
$container
    ->register('my_service', 'Monolog\Processor\IntrospectionProcessor')
    ->addTag('monolog.processor', array('handler' => 'firephp'))
;

通过使用 channel 属性,你也可以把处理添加到一个特定的日志频道。下例只在Security组件所用的 security 日志频道(logging channel)中注册processor:

1
2
3
4
5
services:
    my_service:
        class: Monolog\Processor\IntrospectionProcessor
        tags:
            - { name: monolog.processor, channel: security }
1
2
3
4
5
6
7
8
9
10
11
<?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="my_service" class="Monolog\Processor\IntrospectionProcessor">
            <tag name="monolog.processor" channel="security" />
        </service>
    </services>
</container>
1
2
3
4
$container
    ->register('my_service', 'Monolog\Processor\IntrospectionProcessor')
    ->addTag('monolog.processor', array('channel' => 'security'))
;

在同一标签中,不可同时使用 handlerchannel 属性,因为handlers是在所有日志频道下共享的。

routing.loader 

作用: 注册一个自定义的服务用于加载路由

要开启一个自定义的routing loader(路由加载器),在你的配置文件中把它添加为服务,并打上 routing.loader 标签:

1
2
3
4
5
services:
    routing.loader.your_loader_name:
        class: Fully\Qualified\Loader\Class\Name
        tags:
            - { name: routing.loader }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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="routing.loader.your_loader_name"
            class="Fully\Qualified\Loader\Class\Name">
 
            <tag name="routing.loader" />
        </service>
    </services>
</container>
1
2
3
4
$container
    ->register('routing.loader.your_loader_name', 'Fully\Qualified\Loader\Class\Name')
    ->addTag('routing.loader')
;

更多信息请参考 如何创建一个自定义的路由加载器

routing.expression_language_provider 

作用: 注册一个provider,用于路由中的表达式语言

这个标签对路由表达式组件自动注册 表达式函数providers。使用这些providers,你可以添加自定义函数到路由表达式语言中。

security.expression_language_provider 

作用: 注册一个provider,用于security中的表达式语言

这个标签对Security表达式组件自动注册 表达式函数providers。使用这些providers,你可以添加自定义函数到Security表达式语言中。

security.remember_me_aware 

作用: 允许remember me(记住我)的authentication方式

这个标签在内部允许运行“记住我”这种认证方式。如果你有一个自定义的认证方法,希望用户能够用到remember-me身份认证,那么你应该使用这个标签。

如果你的自定义authentication factory继承的是 AbstractFactory 并且你的authentication listener继承了 AbstractAuthenticationListener,那么你的自定义authentication listener将被自动打上这个标签,并且自动实现功能。

security.voter 

作用: 为Symfony的authorization逻辑添加一个自定义voter

当你对Symfony的authorization checker调用 isGranted 方法时,背后的一个“voter”系统被用于决定“用户是否能够访问”。 security.voter 标签允许你添加自定义的voter到那个表决系统中。

更多信息请参考 如何使用 Voter 检查用户权限 一文。

serializer.encoder 

作用:serializer 服务中注册一个新的encoder

打了这个标签的类必须实现 EncoderInterfaceDecoderInterface 这两个接口。

更多信息请参考 如何使用序列化 一文。

serializer.normalizer 

作用:serializer 服务中注册一个新的normalizer

打了这个标签的类必须实现 NormalizerInterfaceDenormalizerInterface 这两个接口。

更多信息请参考 如何使用序列化 一文。

swiftmailer.default.plugin 

作用: 注册一个自定义的SwiftMailer插件

如果你正使用自定义的SwiftMailer plugin(或者想创建一个),你可以为这个plugin创建一个服务并打上 swiftmailer.default.plugin tag(该标签无选项可用),就能把它注册到SwiftMailer了。

该标签名称中的 default 是mailer的名字。如果你配置了多个mailer,或者出于某种理由而改变了默认mailer的名字,你应该把它(此处的default)改成你的mailer的名字,这样才可使用此标签。

SwiftMailer plugin必须实现 Swift_Events_EventListener 接口。关于plugin的更多信息请参考 SwiftMailer插件文档

有几个SwiftMailer插件是Symfony的核心功能,可以通过不同的配置来激活。详情参考 SwiftmailerBundle配置信息

templating.helper 

作用: 令你的服务能够在PHP templates中使用

要开启自定义的模板助手,把它作为常规服务添加到任意配置文件中,并打上 templating.helper 标签,然后定义一个 alias 属性(helper将通过这个假名在模板中被访问到):

1
2
3
4
5
services:
    templating.helper.your_helper_name:
        class: Fully\Qualified\Helper\Class\Name
        tags:
            - { name: templating.helper, alias: alias_name }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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="templating.helper.your_helper_name"
            class="Fully\Qualified\Helper\Class\Name">
 
            <tag name="templating.helper" alias="alias_name" />
        </service>
    </services>
</container>
1
2
3
4
$container
    ->register('templating.helper.your_helper_name', 'Fully\Qualified\Helper\Class\Name')
    ->addTag('templating.helper', array('alias' => 'alias_name'))
;

translation.loader 

作用: 注册一个自定义的服务用于加载翻译组件

默认时,翻译信息是从文件系统中以多种格式(YAML, XLIFF, PHP,等等)被加载。

在组件章节了解如何加载自定义格式

1
2
3
4
5
services:
    main.translation.my_custom_loader:
        class: Acme\MainBundle\Translation\MyCustomLoader
        tags:
            - { name: translation.loader, alias: bin }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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="main.translation.my_custom_loader"
            class="Acme\MainBundle\Translation\MyCustomLoader">
 
            <tag name="translation.loader" alias="bin" />
        </service>
    </services>
</container>
1
2
3
4
5
6
7
$container
    ->register(
        'main.translation.my_custom_loader',
        'Acme\MainBundle\Translation\MyCustomLoader'
    )
    ->addTag('translation.loader', array('alias' => 'bin'))
;

alias 是必须的,而且极为重要:它定义了“使用这个loader”的翻译文件将要用到的“后缀”。例如,假设你有一些自定义的 bin 格式需要加载。如果你有一个 bin 文件包含了“作用于 message domain”的法语翻译信息,那么你应该有一个这样一个文件: app/Resources/translations/messages.fr.bin

当Symfony尝试加载这个 bin 文件时,它会把你这个自定义加载器的路径作为 $resource 参数来传入。然后你就可以对那个文件展开任何你需要的逻辑,为的是加载你的翻译信息。

如果你从数据库里加载翻译信息,你仍然需要一个resource翻译源文件,但它可以是空的,或者包含一点“从数据库中加载那些翻译源”的相关信息。这个文件是触发你自定义loader的 load 方法的关键。

translation.extractor 

作用: 注册一个自定义的服务,用于从一个文件中提取翻译信息

当执行 translation:update 命令时,它使用提取器(extractors)从一个文件中来提取翻译信息。默认时,Symfony框架有一个 TwigExtractor 和一个 PhpExtractor,它们帮你从Twig模板和PHP模板中发现并提取出待译的键。

你可以创建自己的提取器,创建一个类去实现 ExtractorInterface 接口,然后对这个服务打上 translation.extractor 标签即可。标签有一个必填的选项: alias,它定义了你的提取器的名字:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// src/Acme/DemoBundle/Translation/FooExtractor.php
namespace Acme\DemoBundle\Translation;
 
use Symfony\Component\Translation\Extractor\ExtractorInterface;
use Symfony\Component\Translation\MessageCatalogue;
 
class FooExtractor implements ExtractorInterface
{
    protected $prefix;
 
    /**
     * Extracts translation messages from a template directory to the catalogue.
     * 从一个模板(所在的)目录中提取出(所有)翻译信息(并提供)给翻译目录。
     */
    public function extract($directory, MessageCatalogue $catalogue)
    {
        // ...
    }
 
    /**
     * Sets the prefix that should be used for new found messages.
     * 设置前缀,它应该被用在“新发现的翻译信息”上面。
     */
    public function setPrefix($prefix)
    {
        $this->prefix = $prefix;
    }
}
1
2
3
4
5
services:
    acme_demo.translation.extractor.foo:
        class: Acme\DemoBundle\Translation\FooExtractor
        tags:
            - { name: translation.extractor, alias: foo }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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="acme_demo.translation.extractor.foo"
            class="Acme\DemoBundle\Translation\FooExtractor">
 
            <tag name="translation.extractor" alias="foo" />
        </service>
    </services>
</container>
1
2
3
4
5
$container->register(
    'acme_demo.translation.extractor.foo',
    'Acme\DemoBundle\Translation\FooExtractor'
)
    ->addTag('translation.extractor', array('alias' => 'foo'));

translation.dumper 

作用: 注册一个自定义的服务用于剥离翻译信息

当一个提取器从模板中提取出全部待译信息(的键)之后,剥离器(dumper)开始执行“把这些信息按照指定的格式给剥离成一个翻译文件”。

Symfony内置了许多dupmers:

创建你自己的dumper时需要去继承 FileDumper 或是去实现 DumperInterface 接口,然后给这个服务打上 translation.dumper 标签。标签有一个选项: alias,它被用来决定“哪个dumper应该被使用”。

1
2
3
4
5
services:
    acme_demo.translation.dumper.json:
        class: Acme\DemoBundle\Translation\JsonFileDumper
        tags:
            - { name: translation.dumper, alias: json }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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="acme_demo.translation.dumper.json"
            class="Acme\DemoBundle\Translation\JsonFileDumper">
 
            <tag name="translation.dumper" alias="json" />
        </service>
    </services>
</container>
1
2
3
4
5
$container->register(
    'acme_demo.translation.dumper.json',
    'Acme\DemoBundle\Translation\JsonFileDumper'
)
    ->addTag('translation.dumper', array('alias' => 'json'));

可在翻译组件的章节中了解如何剥离出一个自定义格式

twig.extension 

作用: 注册一个自定义的Twig扩展

要开启Twig扩展,在你的配置文件中把它添加为服务,并打上 Twig.extension 标签:

1
2
3
4
5
services:
    twig.extension.your_extension_name:
        class: Fully\Qualified\Extension\Class\Name
        tags:
            - { name: twig.extension }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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="twig.extension.your_extension_name"
            class="Fully\Qualified\Extension\Class\Name">
 
            <tag name="twig.extension" />
        </service>
    </services>
</container>
1
2
3
4
5
6
7
$container
    ->register(
        'twig.extension.your_extension_name',
        'Fully\Qualified\Extension\Class\Name'
    )
    ->addTag('twig.extension')
;

关于如何真正创建一个Twig Extension类的信息,参考 Twig文档 上的章节,或者阅读 如何写一个自定义的Twig扩展 一文。

在开始写扩展之前,看一下 Twig official extension repository(Twig官方扩展宝库),这里面已经包括了一些有用的扩展。例如 Intl 和它的 localizeddate 变量调节器,可以根据用户的locale来格式化日期。这些官方扩展,也应该作为常规的服务来添加(到配置文件中):

1
2
3
4
5
services:
    twig.extension.intl:
        class: Twig_Extensions_Extension_Intl
        tags:
            - { name: twig.extension }
1
2
3
4
5
6
7
8
9
10
11
<?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="twig.extension.intl" class="Twig_Extensions_Extension_Intl">
            <tag name="twig.extension" />
        </service>
    </services>
</container>
1
2
3
4
$container
    ->register('twig.extension.intl', 'Twig_Extensions_Extension_Intl')
    ->addTag('twig.extension')
;

twig.loader 

作用: 注册一个自定义的服务用于加载Twig模板

默认时,Symfony仅使用一个 Twig Loader - FilesystemLoader。如果你需要从其他资源(resource)中加载Twig模板,你可以为这个新的loader创建一个服务并给它打上 twig.loader 标签:

1
2
3
4
5
services:
    acme.demo_bundle.loader.some_twig_loader:
        class: Acme\DemoBundle\Loader\SomeTwigLoader
        tags:
            - { name: twig.loader, priority: 0 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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="acme.demo_bundle.loader.some_twig_loader"
            class="Acme\DemoBundle\Loader\SomeTwigLoader">
 
            <tag name="twig.loader" priority="0" />
        </service>
    </services>
</container>
1
2
3
4
5
6
7
$container
    ->register(
        'acme.demo_bundle.loader.some_twig_loader',
        'Acme\DemoBundle\Loader\SomeTwigLoader'
    )
    ->addTag('twig.loader', array('priority' => 0))
;

priority 的值是可选的,默认是 0 。愈高,则加载器愈早被调动。

validator.constraint_validator 

作用: 创建你自己的自定义validation约束

这个标签允许创建和注册你自己的自定义validation contraint(验证约束)。更多信息请参考 如何创建一个自定义的验证约束

validator.initializer 

作用: 注册一个自定义的服务,用于在验证开始之前初始化对象

这个标签实现了一个非比寻常的功能,让你在一个对象即将被验证之前,对它进行某些类型的操作。例如,它被Doctrine用来 “在一个对象被验证之前” 查询出它的所有lazily-loaded(懒加载)数据。若没有这个,Doctrine entity 就会在验证时显示 “missing(遗失)”,尽管实际情况并非如此。

如果你需要使用此标签,只需创建一个新类,去实现 ObjectInitializerInterface 接口。然后,给它打上 validator.initializer 标签(它没有选项可用)。

相关实例,见Doctrine Bridge中的 EntityInitializer 类。

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

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