內建 Symfony 服務標籤
服務標籤是 DependencyInjection 元件用來標記需要特殊處理的服務的機制,例如主控台命令或 Twig 擴充功能。
本文展示了 Symfony 元件提供的最常見標籤,但在您的應用程式中,可能還有第三方套件提供的更多標籤。
執行此命令以顯示應用程式中已標記的服務
1
$ php bin/console debug:container --tags
若要搜尋特定標籤,請使用搜尋詞彙重新執行此命令
1
$ php bin/console debug:container --tag=form.type
assets.package
用途:將資源套件新增至應用程式
這是宣告 資源套件的替代方法。套件名稱會依此順序設定
- 首先,標籤的
package
屬性; - 然後,如果已定義靜態方法
getDefaultPackageName()
傳回的值; - 最後,服務名稱。
1 2 3 4
services:
App\Assets\AvatarPackage:
tags:
- { name: assets.package, package: avatars }
現在您可以在範本中使用 avatars
套件
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
等)。然後,它會傳播到這些服務的所有依賴項,事件監聽器除外,在事件監聽器中,只有列出的事件會傳播到其相關的監聽器。
它將在快取中針對產生的服務工廠,用純內聯 include_once
取代 PHP 自動載入。好處是完全繞過服務及其類別階層的自動載入器。結果是顯著的效能提升。
請非常謹慎地使用此標籤,您必須確定始終使用已標記的服務。
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
命令時,就會發生快取清除。如果您的套件快取檔案,您應該新增自訂快取清除器,以便在快取清除程序期間清除這些檔案。
為了註冊您的自訂快取清除器,您必須先建立一個服務類別
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 將不會嘗試在後續請求中再次執行它。因此,您的應用程式和/或套件應該為快取暖機器產生的內容不可用做好準備。
除了您自己的快取暖機器之外,Symfony 元件和第三方套件也為其自身用途定義了快取暖機器。您可以使用以下命令列出所有這些暖機器
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
用途:存取和使用目前的語言環境
設定和擷取語言環境可以透過組態或使用容器參數、監聽器、路由參數或目前的請求來完成。
借助 Translation
合約,可以透過服務設定語言環境。
若要註冊您自己的語言環境感知服務,請先建立一個實作 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 可讓您在多個記錄通道之間共用其處理器。記錄器服務使用通道 app
,但您可以在服務中注入記錄器時變更通道。
1 2 3 4 5
services:
App\Log\CustomLogger:
arguments: ['@logger']
tags:
- { name: monolog.logger, channel: app }
monolog.processor
用途:為記錄新增自訂處理器
Monolog 可讓您在記錄器或處理器中新增處理器,以便在記錄中新增額外資料。處理器接收記錄作為引數,並且必須在 extra
記錄的屬性中新增一些額外資料後傳回記錄。
內建 IntrospectionProcessor
可用於新增觸發記錄器的檔案、行、類別和方法。
您可以全域新增處理器
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
目的: 在序列化器服務中註冊新的正規化器
已標記的類別應實作 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
格式。如果您有一個包含 messages
網域的法語翻譯的 bin
檔案,那麼您可能會有一個檔案 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 載入器 - 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
類別。