跳到内容

内置 Symfony 服务标签

编辑此页

服务标签DependencyInjection 组件 用来标记需要特殊处理的服务的机制,例如控制台命令或 Twig 扩展。

本文展示了 Symfony 组件提供的最常用标签,但在你的应用中,可能还有第三方 bundle 提供的更多标签。

运行以下命令以显示你的应用中已标记的服务

1
$ php bin/console debug:container --tags

要搜索特定标签,请使用搜索词重新运行此命令

1
$ php bin/console debug:container --tag=form.type

assets.package

用途:向应用程序添加 asset package

这是声明 asset package 的另一种方式。package 的名称按以下顺序设置

  • 首先,标签的 package 属性;
  • 然后,如果定义了静态方法 getDefaultPackageName(),则返回该方法的值;
  • 最后,服务名称。
1
2
3
4
services:
    App\Assets\AvatarPackage:
        tags:
            - { name: assets.package, package: avatars }

现在你可以在模板中使用 avatars package 了

1
<img src="{{ asset('...', 'avatars') }}">

auto_alias

用途:基于容器参数的值定义别名

考虑以下配置,它定义了三个不同但相关的服务

1
2
3
4
5
6
7
services:
    app.mysql_lock:
        class: App\Lock\MysqlLock
    app.postgresql_lock:
        class: App\Lock\PostgresqlLock
    app.sqlite_lock:
        class: App\Lock\SqliteLock

你的应用不需要处理这三个服务,而是需要一个通用的 app.lock 服务,它将是其中一个服务的别名,具体取决于某些配置。 借助 auto_alias 选项,你可以根据配置参数的值自动创建该别名。

假设存在一个名为 database_type 的配置参数。 那么,通用的 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" }

format 选项定义了用于构造要别名的服务名称的表达式。 此表达式可以使用任何容器参数(像往常一样,用 % 字符包裹它们的名称)。

注意

当使用 auto_alias 标签时,不强制要求将别名服务定义为私有。 但是,这样做(如上面的示例中所示)在大多数情况下是有意义的,可以防止直接访问这些服务,而不是使用通用服务别名。

console.command

用途:向应用程序添加命令

有关在服务容器中注册你自己的命令的详细信息,请阅读 如何将命令定义为服务

container.hot_path

用途:添加到始终需要的服务列表

此标签标识始终需要的服务。 它仅应用于非常短的引导服务列表(例如 routerevent_dispatcherhttp_kernelrequest_stack 等)。 然后,它会传播到这些服务的所有依赖项,事件监听器是一个特例,其中只有列出的事件才会传播到其相关的监听器。

在生成的服务工厂的缓存中,它将 PHP 自动加载替换为纯内联 include_once。 好处是完全绕过服务及其类层次结构的自动加载器。 结果是显着的性能提升。

请谨慎使用此标签,你必须确保始终使用标记的服务。

container.no_preload

用途:从 PHP 预加载的类列表中删除类

将此标签添加到服务,当使用 PHP 类预加载 时,将不会预加载其类

1
2
3
services:
    App\SomeNamespace\SomeService:
        tags: ['container.no_preload']

如果你将一些标记为 container.no_preload 的服务添加为另一个服务的参数,则 container.no_preload 标签也会自动应用于该服务。

container.preload

用途:将某些类添加到 PHP 预加载的类列表中

当使用 PHP 类预加载 时,此标签允许你定义应预加载哪些 PHP 类。 这可以通过使你的服务使用的一些类始终可用于所有请求(直到服务器重新启动)来提高性能

1
2
3
4
5
6
services:
    App\SomeNamespace\SomeService:
        tags:
            - { name: 'container.preload', class: 'App\SomeClass' }
            - { name: 'container.preload', class: 'App\Some\OtherClass' }
            # ...

controller.argument_value_resolver

用途:注册控制器参数(例如 Request)的值解析器

值解析器实现了 ValueResolverInterface,用于解析控制器的参数值,如此处所述:扩展操作参数解析

data_collector

用途:创建一个收集分析器自定义数据的类

有关创建你自己的自定义数据收集的详细信息,请阅读 分析器 文章。

doctrine.event_listener

用途:添加 Doctrine 事件监听器

有关创建 Doctrine 事件监听器的详细信息,请阅读 Doctrine 事件 文章。

doctrine.event_subscriber

用途:添加 Doctrine 事件订阅器

有关创建 Doctrine 事件订阅器的详细信息,请阅读 Doctrine 事件 文章。

form.type

用途:创建自定义表单字段类型

有关创建你自己的自定义表单类型的详细信息,请阅读 如何创建自定义表单字段类型 文章。

form.type_extension

用途:创建自定义“表单扩展”

有关创建表单类型扩展的详细信息,请阅读 如何创建表单类型扩展 文章。

form.type_guesser

用途:添加你自己的“表单类型猜测”逻辑

此标签允许你将自己的逻辑添加到 表单猜测 过程中。 默认情况下,表单猜测由基于验证元数据和 Doctrine 元数据(如果你正在使用 Doctrine)或 Propel 元数据(如果你正在使用 Propel)的“猜测器”完成。

另请参阅

有关如何创建你自己的类型猜测器的信息,请参阅 创建自定义类型猜测器

kernel.cache_clearer

用途:注册你的服务以便在清除缓存过程中调用

每当你调用 cache:clear 命令时,都会发生缓存清除。 如果你的 bundle 缓存文件,你应该添加自定义缓存清除器,以便在缓存清除过程中清除这些文件。

为了注册你的自定义缓存清除器,首先你必须创建一个服务类

1
2
3
4
5
6
7
8
9
10
11
12
// src/Cache/MyClearer.php
namespace App\Cache;

use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;

class MyClearer implements CacheClearerInterface
{
    public function clear(string $cacheDirectory): void
    {
        // clear your cache
    }
}

如果你正在使用 默认的 services.yaml 配置,你的服务将自动标记为 kernel.cache_clearer。 但是,你也可以手动注册它

1
2
3
services:
    App\Cache\MyClearer:
        tags: [kernel.cache_clearer]

kernel.cache_warmer

用途:注册你的服务以便在缓存预热过程中调用

每当你运行 cache:warmupcache:clear 命令时(除非你将 --no-warmup 传递给 cache:clear),都会发生缓存预热。 当处理请求时,如果尚未被其中一个命令完成,它也会运行。

目的是初始化应用程序需要的任何缓存,并防止第一个用户遇到任何显着的“缓存命中”,在这种情况下,缓存是动态生成的。

要注册你自己的缓存预热器,首先创建一个实现 CacheWarmerInterface 接口的服务

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
29
// src/Cache/MyCustomWarmer.php
namespace App\Cache;

use App\Foo\Bar;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;

class MyCustomWarmer implements CacheWarmerInterface
{
    public function warmUp(string $cacheDir, ?string $buildDir = null): array
    {
        // ... do some sort of operations to "warm" your cache

        $filesAndClassesToPreload = [];
        $filesAndClassesToPreload[] = Bar::class;

        foreach (scandir($someCacheDir) as $file) {
            if (!is_dir($file = $someCacheDir.'/'.$file)) {
                $filesAndClassesToPreload[] = $file;
            }
        }

        return $filesAndClassesToPreload;
    }

    public function isOptional(): bool
    {
        return true;
    }
}

warmUp() 方法必须返回一个数组,其中包含要预加载的文件和类。 文件必须是绝对路径,类必须是完全限定的类名。 唯一的限制是文件必须存储在缓存目录中。 如果你不需要预加载任何内容,则返回一个空数组。 如果需要创建只读工件,你可以使用 warmUp() 方法的 $buildDir 参数将它们存储在不同的目录中。

如果可以在不调用此缓存预热器的情况下使用应用程序,则 isOptional() 方法应返回 true。 在 Symfony 中,可选的预热器始终默认执行(你可以通过在使用命令时使用 --no-optional-warmers 选项来更改此设置)。

如果你正在使用 默认的 services.yaml 配置,你的服务将自动标记为 kernel.cache_warmer。 但是,你也可以手动注册它

1
2
3
4
services:
    App\Cache\MyCustomWarmer:
        tags:
            - { name: kernel.cache_warmer, priority: 0 }

注意

priority 是可选的,其值是正整数或负整数,默认为 0。 数字越高,预热器执行得越早。

警告

如果你的缓存预热器由于任何异常而执行失败,Symfony 将不会尝试为后续请求再次执行它。 因此,你的应用程序和/或 bundle 应该为缓存预热器生成的内容不可用时做好准备。

除了你自己的缓存预热器之外,Symfony 组件和第三方 bundle 也为自己的目的定义了缓存预热器。 你可以使用以下命令列出所有这些预热器

1
$ php bin/console debug:container --tag=kernel.cache_warmer

kernel.event_listener

用途:监听 Symfony 中的不同事件/钩子

在 Symfony 应用程序的执行期间,会触发不同的事件,你也可以调度自定义事件。 此标签允许你将你自己的类挂钩到任何这些事件中。

有关此监听器的完整示例,请阅读 事件和事件监听器 文章。

核心事件监听器参考

有关与每个内核事件关联的事件监听器的参考,请参阅 Symfony 事件参考

kernel.event_subscriber

用途:订阅 Symfony 中的一组不同事件/钩子

这是创建事件监听器的另一种方式,并且是推荐的方式(而不是使用 kernel.event_listener)。 请参阅 事件和事件监听器

kernel.fragment_renderer

用途:添加新的 HTTP 内容渲染策略

要添加新的渲染策略(除了像 EsiFragmentRenderer 这样的核心策略之外),请创建一个实现 FragmentRendererInterface 的类,将其注册为服务,然后使用 kernel.fragment_renderer 标记它。

kernel.locale_aware

用途:访问和使用当前的 locale

可以通过配置或使用容器参数、监听器、路由参数或当前请求来设置和检索 locale。

借助 Translation 契约,可以通过服务设置 locale。

要注册你自己的 locale 感知服务,首先创建一个实现 LocaleAwareInterface 接口的服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// src/Locale/MyCustomLocaleHandler.php
namespace App\Locale;

use Symfony\Contracts\Translation\LocaleAwareInterface;

class MyCustomLocaleHandler implements LocaleAwareInterface
{
    public function setLocale(string $locale): void
    {
        $this->locale = $locale;
    }

    public function getLocale(): string
    {
        return $this->locale;
    }
}

如果你正在使用 默认的 services.yaml 配置,你的服务将自动标记为 kernel.locale_aware。 但是,你也可以手动注册它

1
2
3
services:
    App\Locale\MyCustomLocaleHandler:
        tags: [kernel.locale_aware]

kernel.reset

用途:在请求之间清理服务

在所有主请求(而非 子请求)中,除了第一个请求之外,Symfony 都会查找任何标记为 kernel.reset 标签的服务,以重新初始化它们的状态。 这是通过调用在标签的 method 参数中配置的方法名的方法来完成的。

当在应用程序服务器中运行你的项目时,这非常有用,这些服务器在请求之间重用 Symfony 应用程序以提高性能。 例如,此标签应用于分析器的内置 数据收集器,以删除它们的所有信息。

mime.mime_type_guesser

用途:添加你自己的逻辑来猜测 MIME 类型

如果 Mime 组件 提供的猜测器不符合你的需求,则可以使用此标签注册你自己的 MIME 类型猜测器

monolog.logger

用途:将自定义日志记录通道与 Monolog 一起使用

Monolog 允许你在多个日志记录通道之间共享其处理程序。 logger 服务使用通道 app,但你可以在将 logger 注入服务时更改通道。

1
2
3
4
5
services:
    App\Log\CustomLogger:
        arguments: ['@logger']
        tags:
            - { name: monolog.logger, channel: app }

提示

你可以创建 自定义通道,甚至 自动装配日志记录通道

monolog.processor

用途:为日志记录添加自定义处理器

Monolog 允许你在 logger 或处理程序中添加处理器,以便在记录中添加额外数据。 处理器接收记录作为参数,并且必须在 extra 属性中添加一些额外数据后返回它。

内置的 IntrospectionProcessor 可用于添加触发 logger 的文件、行、类和方法。

你可以全局添加处理器

1
2
3
services:
    Monolog\Processor\IntrospectionProcessor:
        tags: [monolog.processor]

提示

如果你的服务不是可调用的(使用 __invoke()),你可以在标签中添加 method 属性以使用特定方法。

你还可以通过使用 handler 属性为特定处理程序添加处理器

1
2
3
4
services:
    Monolog\Processor\IntrospectionProcessor:
        tags:
            - { name: monolog.processor, handler: firephp }

你还可以通过使用 channel 属性为特定日志记录通道添加处理器。 这将仅为 Security 组件中使用的 security 日志记录通道注册处理器

1
2
3
4
services:
    Monolog\Processor\IntrospectionProcessor:
        tags:
            - { name: monolog.processor, channel: security }

注意

你不能为同一标签同时使用 handlerchannel 属性,因为处理程序在所有通道之间共享。

routing.loader

用途:注册加载路由的自定义服务

要启用自定义路由加载器,请将其作为常规服务添加到你的配置之一,并使用 routing.loader 标记它

1
2
3
services:
    App\Routing\CustomLoader:
        tags: [routing.loader]

有关更多信息,请参阅 如何创建自定义路由加载器

routing.expression_language_provider

用途:在路由中注册表达式语言函数的提供程序

此标签用于自动注册路由表达式组件的 表达式函数提供程序。 使用这些提供程序,你可以向路由表达式语言添加自定义函数。

security.expression_language_provider

用途:在安全性方面注册表达式语言函数的提供程序

此标签用于自动注册安全表达式组件的 表达式函数提供程序。 使用这些提供程序,你可以向安全表达式语言添加自定义函数。

security.voter

用途:向 Symfony 的授权逻辑添加自定义投票器

当你在 Symfony 的授权检查器上调用 isGranted() 时,幕后会使用“投票器”系统来确定用户是否应该具有访问权限。 security.voter 标签允许你向该系统添加你自己的自定义投票器。

有关更多信息,请阅读 如何使用投票器检查用户权限 文章。

serializer.encoder

用途:在 serializer 服务中注册新的编码器

标记的类应实现 EncoderInterfaceDecoderInterface

有关更多详细信息,请参阅 如何使用序列化器

serializer.normalizer

用途:在 Serializer 服务中注册新的规范化器

标记的类应实现 NormalizerInterfaceDenormalizerInterface

有关更多详细信息,请参阅 如何使用序列化器

运行以下命令以检查默认规范化器的优先级

1
$ php bin/console debug:container --tag serializer.normalizer

translation.loader

用途:注册加载翻译的自定义服务

默认情况下,翻译是从文件系统中以各种不同的格式(YAML、XLIFF、PHP 等)加载的。

现在,将你的加载器注册为服务,并使用 translation.loader 标记它

1
2
3
4
services:
    App\Translation\MyCustomLoader:
        tags:
            - { name: translation.loader, alias: bin }

alias 选项是必需的且非常重要:它定义了用于使用此加载器的资源文件的文件“后缀”。例如,假设您有一些需要加载的自定义 bin 格式。如果您有一个 bin 文件,其中包含 messages 域的法语翻译,那么您可能有一个文件 translations/messages.fr.bin

当 Symfony 尝试加载 bin 文件时,它会将路径作为 $resource 参数传递给您的自定义加载器。然后,您可以对该文件执行任何所需的逻辑,以便加载您的翻译。

如果您要从数据库加载翻译,您仍然需要一个资源文件,但它可能是空白的,或者包含一些关于从数据库加载这些资源的信息。该文件是触发自定义加载器上的 load() 方法的关键。

translation.extractor

目的:注册一个自定义服务,用于从文件中提取消息

当执行 translation:extract 命令时,它使用提取器从文件中提取翻译消息。默认情况下,Symfony 框架有一个 TwigExtractor,用于从 Twig 模板中查找和提取翻译键。

如果您还想从 PHP 文件中查找和提取翻译键,请安装以下依赖项以激活 PhpAstExtractor

1
$ composer require nikic/php-parser

您可以通过创建一个实现 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
// 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 string $prefix;

    /**
     * Extracts translation messages from a template directory to the catalog.
     */
    public function extract(string $directory, MessageCatalogue $catalog): void
    {
        // ...
    }

    /**
     * Sets the prefix that should be used for new found messages.
     */
    public function setPrefix(string $prefix): void
    {
        $this->prefix = $prefix;
    }
}
1
2
3
4
services:
    App\Translation\CustomExtractor:
        tags:
            - { name: translation.extractor, alias: foo }

translation.dumper

目的:注册一个自定义服务,用于将消息转储到文件

翻译提取器 从模板中提取所有消息后,将执行转储器以将消息转储为特定格式的翻译文件。

Symfony 已经带有许多转储器

您可以通过扩展 FileDumper 或实现 DumperInterface 接口,并将服务标记为 translation.dumper 来创建您自己的转储器。该标签有一个选项:alias。这是用于确定应使用哪个转储器的名称。

1
2
3
4
services:
    App\Translation\JsonFileDumper:
        tags:
            - { name: translation.dumper, alias: json }

translation.provider_factory

目的:注册与自定义翻译提供程序相关的工厂

在创建自定义 翻译提供程序 时,您必须将您的工厂注册为服务,并使用 translation.provider_factory 标记它

1
2
3
4
services:
    App\Translation\CustomProviderFactory:
        tags:
            - { name: translation.provider_factory }

twig.extension

目的:注册自定义 Twig 扩展

要启用 Twig 扩展,请将其作为常规服务添加到您的配置之一中,并使用 twig.extension 标记它。如果您正在使用 默认的 services.yaml 配置,则该服务会自动注册和自动标记。但是,您也可以手动注册它

1
2
3
4
5
6
7
8
9
services:
    App\Twig\AppExtension:
        tags: [twig.extension]

    # optionally you can define the priority of the extension (default = 0).
    # Extensions with higher priorities are registered earlier. This is mostly
    # useful to register late extensions that override other extensions.
    App\Twig\AnotherExtension:
        tags: [{ name: twig.extension, priority: -100 }]

有关如何创建实际 Twig 扩展类的信息,请参阅 Twig 的文档 中的相关主题,或阅读 创建和使用模板 文章。

twig.loader

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

默认情况下,Symfony 仅使用一个 Twig Loader - FilesystemLoader。如果您需要从另一个资源加载 Twig 模板,您可以为新的加载器创建一个服务,并使用 twig.loader 标记它。

如果您使用 默认的 services.yaml 配置,则该服务将由于自动配置而自动标记。但是,您也可以手动注册它

1
2
3
4
services:
    App\Twig\CustomLoader:
        tags:
            - { name: twig.loader, priority: 0 }

注意

priority 是可选的,其值是正整数或负整数,默认为 0。数字较高的加载器会先尝试。

twig.runtime

目的:注册自定义延迟加载的 Twig 扩展

延迟加载的 Twig 扩展 被定义为常规服务,但它们需要使用 twig.runtime 标记。如果您正在使用 默认的 services.yaml 配置,则该服务会自动注册和自动标记。但是,您也可以手动注册它

1
2
3
services:
    App\Twig\AppExtension:
        tags: [twig.runtime]

validator.constraint_validator

目的:创建您自己的自定义验证约束

此标签允许您创建和注册您自己的自定义验证约束。有关更多信息,请阅读 如何创建自定义验证约束 文章。

validator.initializer

目的:注册一个在验证之前初始化对象的服务

此标签提供了一个非常不常见的功能,允许您在对象验证之前对其执行某种操作。例如,Doctrine 使用它来查询对象上所有延迟加载的数据,然后再进行验证。如果没有这个,Doctrine 实体上的一些数据在验证时会显示为“丢失”,即使情况并非如此。

如果您确实需要使用此标签,只需创建一个新的类,实现 ObjectInitializerInterface 接口。然后,使用 validator.initializer 标签标记它(它没有选项)。

有关示例,请参阅 Doctrine Bridge 内的 DoctrineInitializer 类。

这项工作,包括代码示例,已根据 Creative Commons BY-SA 3.0 许可获得许可。
目录
    版本