内置 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
标签时,不强制要求将别名服务定义为私有。 但是,这样做(如上面的示例中所示)在大多数情况下是有意义的,可以防止直接访问这些服务,而不是使用通用服务别名。
container.hot_path
用途:添加到始终需要的服务列表
此标签标识始终需要的服务。 它仅应用于非常短的引导服务列表(例如 router
、event_dispatcher
、http_kernel
、request_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,用于解析控制器的参数值,如此处所述:扩展操作参数解析。
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:warmup
或 cache: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 应用程序以提高性能。 例如,此标签应用于分析器的内置 数据收集器,以删除它们的所有信息。
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 }
注意
你不能为同一标签同时使用 handler
和 channel
属性,因为处理程序在所有通道之间共享。
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
服务中注册新的编码器
标记的类应实现 EncoderInterface 和 DecoderInterface。
有关更多详细信息,请参阅 如何使用序列化器。
serializer.normalizer
用途:在 Serializer 服务中注册新的规范化器
标记的类应实现 NormalizerInterface 和 DenormalizerInterface。
有关更多详细信息,请参阅 如何使用序列化器。
运行以下命令以检查默认规范化器的优先级
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 已经带有许多转储器
- CsvFileDumper
- IcuResFileDumper
- IniFileDumper
- MoFileDumper
- PoFileDumper
- QtFileDumper
- XliffFileDumper
- YamlFileDumper
您可以通过扩展 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.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.initializer
目的:注册一个在验证之前初始化对象的服务
此标签提供了一个非常不常见的功能,允许您在对象验证之前对其执行某种操作。例如,Doctrine 使用它来查询对象上所有延迟加载的数据,然后再进行验证。如果没有这个,Doctrine 实体上的一些数据在验证时会显示为“丢失”,即使情况并非如此。
如果您确实需要使用此标签,只需创建一个新的类,实现 ObjectInitializerInterface 接口。然后,使用 validator.initializer
标签标记它(它没有选项)。
有关示例,请参阅 Doctrine Bridge 内的 DoctrineInitializer
类。