Alias (Псевдонимы)
По умолчанию: []
Механизм псевдонимов позволяет заменять одну зависимость другой. Это полезно для:
- Выбора реализации интерфейса - указание, какой конкретный класс использовать для интерфейса.
- Выбора наследника абстрактного класса - определение конкретной реализации абстрактного класса.
- Замены зависимостей - использование подклассов вместо родительских классов.
- Сокращения имен - создание коротких псевдонимов для длинных имен классов
📋 Базовый пример
<?php
declare(strict_types=1);
namespace App;
class Example {
public function __construct(
public I $i,
public Base $base,
) {}
}
interface I {}
class R1 implements I {}
class R2 implements I {}
class Base {}
class E1 extends Base {}
class E2 extends Base {}
new \Cekta\DI\Compiler(
containers: [Example::class],
alias: [
I::class => R2::class, // Для I используем R2
Base::class => E1::class, // Для Base используем E1
'short-name' => Example::class, // Создаем короткий псевдоним
],
fqcn: 'App\\Runtime\\Container',
);
Использование:
<?php
declare(strict_types=1);
namespace App;
$container = new \App\Runtime\Container([]);
$example = $container->get(Example::class);
$example->i instanceof R2; // true
$example->base instanceof E1; // true
$example === $container->get('short-name'); // true
Важно: Псевдонимы устанавливаются на этапе компиляции. Для их изменения требуется повторная генерация контейнера.
🎯 Псевдонимы для конкретных зависимостей
Можно задавать псевдонимы, которые применяются только к определенным аргументам.
Синтаксис:
{ClassName}${argumentName} => {target}
Пример:
<?php
declare(strict_types=1);
namespace App;
class Example {
public function __construct(
public I $i,
public I $i2, // Этот аргумент получит особую реализацию
public I $i3,
) {}
}
interface I {}
class R1 implements I {}
class R2 implements I {}
new \Cekta\DI\Compiler(
containers: [Example::class],
alias: [
I::class => R2::class, // По умолчанию для I используем R2
Example::class . '$i2' => R1::class, // Но для $i2 в Example используем R1
],
fqcn: 'App\\Runtime\\Container',
);
Использование:
<?php
declare(strict_types=1);
namespace App;
$container = new \App\Runtime\Container([]);
$example = $container->get(Example::class);
$example->i instanceof R2; // true
$example->i2 instanceof R1; // true - переопределен!
$example->i3 instanceof R2; // true
💡 Приоритеты применения
При разрешении зависимостей учитывается следующий порядок приоритетов:
- Конкретный аргумент (
ClassName$argumentName) - наивысший приоритет - Общий псевдоним - применяется ко всем использованиям класса/интерфейса
- Autowiring - если псевдоним не задан, используется стандартное разрешение
🚀 Типичные сценарии использования
1. Выбор реализации интерфейса
alias: [
LoggerInterface::class => FileLogger::class,
CacheInterface::class => RedisCache::class,
]
2. Работа с абстрактными классами
alias: [
AbstractRepository::class => UserRepository::class,
AbstractService::class => UserService::class,
]
3. Сокращение длинных имен
alias: [
'users' => \App\Domain\User\Services\UserManagementService::class,
'auth' => \App\Domain\Auth\Services\AuthenticationService::class,
]
4. Замена реализации в определенном месте
alias: [
MailerInterface::class => SmtpMailer::class,
NewsletterService::class . '$mailer' => TestMailer::class, // Только для NewsletterService
]
⚠️ Важные замечания
- Изменения требуют перекомпиляции - псевдонимы фиксируются при генерации контейнера
- Совместимость типов - заменяемый класс должен быть совместим по типу (реализовывать интерфейс или наследовать класс)
- Проверка на этапе компиляции - ошибки несовместимости типов обнаруживаются при генерации кода
🔄 Совместное использование с другими механизмами
Псевдонимы хорошо работают в сочетании с:
- Params - для передачи конкретных значений
- Autowiring - для автоматического разрешения оставшихся зависимостей
- Lazy-зависимостями - для отложенного создания объектов
Пример комплексного использования:
new \Cekta\DI\Compiler(
containers: [Controller::class],
alias: [
RepositoryInterface::class => DatabaseRepository::class,
Controller::class . '$logger' => FileLogger::class,
],
params: [
'database.dsn' => 'mysql:host=localhost;dbname=app',
Controller::class . '$debug' => true,
],
);
Псевдонимы - мощный инструмент для гибкой настройки зависимостей, позволяющий легко менять реализации без изменения основного кода