跳到內容

內建 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 標籤時,不強制要求將別名服務定義為私有。但是,這樣做(如上述範例所示)在大多數情況下是有意義的,可以防止直接存取這些服務,而不是使用通用服務別名。

console.command

用途:將命令新增至應用程式

有關在服務容器中註冊您自己的命令的詳細資訊,請閱讀如何將命令定義為服務

container.hot_path

用途:新增至始終需要的服務清單

此標籤識別始終需要的服務。它僅適用於非常短的引導服務清單(例如 routerevent_dispatcherhttp_kernelrequest_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,並用於解析控制器的引數值,如此處所述:擴充動作引數解析

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 命令時,就會發生快取清除。如果您的套件快取檔案,您應該新增自訂快取清除器,以便在快取清除程序期間清除這些檔案。

為了註冊您的自訂快取清除器,您必須先建立一個服務類別

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 將不會嘗試在後續請求中再次執行它。因此,您的應用程式和/或套件應該為快取暖機器產生的內容不可用做好準備。

除了您自己的快取暖機器之外,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 應用程式以提高效能的應用程式伺服器中執行專案時,這最有用。例如,此標籤適用於效能分析器的內建資料收集器,以刪除其所有資訊。

mime.mime_type_guesser

用途:新增您自己的邏輯來猜測 MIME 類型

如果 Mime 元件提供的猜測器不符合您的需求,則此標籤用於註冊您自己的 MIME 類型猜測器

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 }

注意

您不能對同一個標籤同時使用 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

目的: 在序列化器服務中註冊新的正規化器

已標記的類別應實作 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 格式。如果您有一個包含 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 已經附帶了許多傾印器

您可以透過擴展 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 載入器 - 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 授權條款授權。
TOC
    版本