Як створювати псевдоніми сервісу та відзначати сервіси як приватні

Дата оновлення перекладу 2024-06-03

Як створювати псевдоніми сервісу та відзначати сервіси як приватні

Відзначення сервісів приватними/публічними

Під час визначення сервісу, його можна зробити публічним або приватним Якщо сервіс публічний, це означає, що ви можете отримати доступ до нього напряму з контейнера під час рантайму. Наприклад, сервіс doctrine є публічним:

1
2
// таким чином можна отримати доступ лише до публічних сервісів
$doctrine = $container->get('doctrine');

Але зазвичай, доступ до сервісів отримують, використовуючи впровадження залежності . І в цьому випадку, ці сервіси не повинні бути публічними.

Так що хіба що вам не потрібно спеціально отримати доступ напряму з контейнера через $container->get(), найкращою практикою буде зробити ваші сервіси приватними. Насправді, конфігурація services.yml за замовчуванням конфігурує всі сервіси так, щоб вони були приватними за замовчуванням.

Ви також можете контролювати опцію public на засаді кожного сервісу:

1
2
3
4
5
6
# config/services.yaml
services:
    # ...

    App\Service\Foo:
        public: true

Приватні сервіси особливі, тому що вони дозволяють контейнеру оптимізувати те, як вони будуть інстанційовані, і чи потрібно це взагалі. Це підвищує продуктивність контейнера. А також надає вам кращі повідомлення про помилки: якщо ви спробуєте послатися на неіснуючий сервіс, то ви отримаєте чітку помилку при оновленні будь-якої сторінки, навіть якщо проблемний код не було запущено на ній.

Тепер, коли сервіс приватний, ви не повинні викликати сервіс напряму з контейнера:

1
2
3
use App\Service\Foo;

$container->get(Foo::class);

Отже, сервіс може бути відзначений як приватний, якщо ви не хочете отримувати до нього доступ напряму з вашого коду. Однак, якщо сервіс було відзначено як приватний, ви все ще можете надати йому псевдонім (див. нижче), щоб отримати доступ до цього сервісу (через псевдонім).

Додавання псевдонімів

Іноді вам може захотітися використати скорочення для доступу до деяких сервісів. Ви можете зробити це, надавши сервісам псевдоніми і, більше того, ви можете давати такі псевдоніми навіть приватним сервісам.

1
2
3
4
5
6
7
8
9
10
11
// src/Mail/PhpMailer.php
namespace App\Mail;

// ...
use Symfony\Component\DependencyInjection\Attribute\AsAlias;

#[AsAlias(id: 'app.mailer', public: true)]
class PhpMailer
{
    // ...
}

Це означає, що при використанні контейнера напряму, ви зможете отримати доступ до сервісу PhpMailer, запитавши сервіс app.mailer таким чином:

1
$container->get('app.mailer'); // Would return a PhpMailer instance

Tip

В YAML ви також можете використати скорочення для псевдоніму сервісу:

1
2
3
4
# config/services.yaml
services:
    # ...
    app.mailer: '@App\Mail\PhpMailer'

Tip

При використанні атрибуту #[AsAlias] можна не передавати аргумент id, якщо клас реалізує лише один інтерфейс. MailerInterface буде псевдонімом PhpMailer:

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

// ...
use Symfony\Component\DependencyInjection\Attribute\AsAlias;
use Symfony\Component\Mailer\MailerInterface;

#[AsAlias]
class PhpMailer implements MailerInterface
{
    // ...
}

Застарівання псевдонімів сервісу

Якщо ви виріщили, що використання псевдоніму сервісу застаріло (так як він некатуальний або ви вирішили більше його не утримувати), ви можете оголосити його визначення застарілим:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
app.mailer:
    alias: 'App\Mail\PhpMailer'

    # це виводить наступне загальне повідомлення про старіння:
    # Починаючи з acme/package 1.2: Псевдонім сервісу "app.mailer" застарів. Вам варто перестати використовувати його, так як він буде видалений у майбутньому
    deprecated:
        package: 'acme/package'
        version: '1.2'

    # ви також можете визначити користувацьке повідомлення про старіння (доступний заповнювач %alias_id% placeholder)
    deprecated:
        package: 'acme/package'
        version: '1.2'
        message: 'The "%alias_id%" alias is deprecated. Do not use it anymore.'

Тепер, кожний раз, коли буде використано цей сервіс, буде викликатися попередження про старіння, яке радитиме вам перестати або змінити використання цього псевдоніму.

Повідомлення насправді є шаблоном, який заміщує появу заміни id сервісу заповнювачем %alias_id%. Ви повинні мати як мінімум одне явлення заповнювача %alias_id% у вашому шаблоні.

Анонімні сервіси

У деяких випадках, вам може захотітися запобігти сервіс від використання в якості залежності інших сервісів. Це може бути досягнуто шляхом створення анонімного сервісу. Ці сервіси схожі на звичайні сервіси, яле вони не визначають ID і вони створюються під час використання.

Наступний приклад демонструє, як впровадити анонімний сервіс в інший сервіс:

1
2
3
4
5
6
# config/services.yaml
services:
    App\Foo:
        arguments:
            - !service
                class: App\AnonymousBar

Note

Анонімні сервіси НЕ наслідують визначення, надані значенням за замовчуванням, визначеними у конфігурації. Тому вам буде потрібно чітко відзначити сервіс як автозмонтований або автосконфігурований при створенні анонімного сервісу наприклад: inline_service(Foo::class)->autowire()->autoconfigure().

Використання анонімного сервісу в якості фабрики виглядає так:

1
2
3
4
# config/services.yaml
services:
    App\Foo:
        factory: [ !service { class: App\FooFactory }, 'constructFoo' ]

Застарівання сервісів

Коли ви вирішили, що використання сервісу застаріло (так як він став неактуальним або ви виріщили його більше не обслуговувати), ви можете оголосити його визначення застарілим:

1
2
3
4
5
6
# config/services.yaml
App\Service\OldService:
    deprecated:
        package: 'vendor-name/package-name'
        version: '2.8'
        message: The "%service_id%" service is deprecated since vendor-name/package-name 2.8 and will be removed in 3.0.

Тепер, кожний раз, коли використовується цей сервіс, викликатиметься попередження про старіння, яке радитиме вам зупинити або змінити використання цього сервісу.

Повідомлення насправді є шаблоном повідомлення, яке замінює появи заповнювача %service_id% id сервісу. Ви повинні мати хоча б одну появу заповнювача %service_id% у вашому шаблоні.

Note

Повідомлення про старіння опціональне. Якщо воно не встановлене, Symfony виведе своє повідомлення за замовчуванням: Сервіс "%service_id%" застарів. Вам варто перестати його використовувати, так як він скоро буде видалений..

Tip

Наполегливо рекомендуємо визначати користувацьке повідомлення, так як повідомлення за замовчуванням занадто загальне. Гарне повідомлення повідомляє про те, коли застарів сервіс, до якого часу він буде підтримуватися та альтернативні сервіси для використання (якщо вони є).

Для декораторів сервісу (див. Як декораувати сервіси), якщо визначення не змінює статус старіння, воно успадкує статус з декорованого визначення.