Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Управление жизненным циклом зависимостей

Библиотека предоставляет три типа жизненного цикла для зависимостей, что особенно полезно в долгоживущих процессах:

  • Приложениях на RoadRunner или FrankenPHP
  • Фоновых workers
  • Консольных командах, обрабатывающих множество задач

Вы можете управлять жизненным циклом любых зависимостей: containers, params, alias и autowiring.

🔄 Типы жизненных циклов

1. Scoped (Область видимости) ⭐ По умолчанию

  • Зависимость создаётся один раз в пределах одного контейнера
  • При создании нового экземпляра контейнера создаётся новая копия зависимости
  • Идеально для обработки отдельных запросов

2. Singleton (Одиночка)

  • Зависимость создаётся один раз на всё время выполнения скрипта
  • Все экземпляры контейнера получают один и тот же объект
  • Используется через параметр singletons в конфигурации

3. Factory (Фабрика)

  • Каждый запрос создаёт новый экземпляр зависимости
  • Используется через параметр factories в конфигурации

📋 Конфигурация

<?php
declare(strict_types=1);

namespace App;

class Scoped {}
class Singleton {}
class Factory {}

new \Cekta\DI\Compiler(
    containers: [
        Scoped::class,
        Singleton::class,
        Factory::class,
    ],
    fqcn: 'App\\Runtime\\Container',
    singletons: [Singleton::class],   // Singleton-зависимости
    factories: [Factory::class],      // Factory-зависимости
    // Scoped-зависимости не указываются явно (используются по умолчанию)
)->compile();

🧪 Пример использования

Демонстрация на GitHub

<?php
declare(strict_types=1);

namespace App;

function testLifecycle(string $className) {
    $container1 = new \App\Runtime\Container();
    $container2 = new \App\Runtime\Container();
    
    $a = $container1->get($className);
    $b = $container1->get($className);  // Второй запрос к тому же контейнеру
    $c = $container2->get($className);  // Запрос к другому контейнеру
    
    echo "Внутри одного контейнера: " . ($a === $b ? "одинаковый" : "разный") . "\n";
    echo "Между разными контейнерами: " . ($a === $c ? "одинаковый" : "разный") . "\n";
    echo "---\n";
}

echo "Scoped (по умолчанию):\n";
testLifecycle(Scoped::class);

echo "Singleton:\n";
testLifecycle(Singleton::class);

echo "Factory:\n";
testLifecycle(Factory::class);

Результат:

Scoped (по умолчанию):
Внутри одного контейнера: одинаковый
Между разными контейнерами: разный
---
Singleton:
Внутри одного контейнера: одинаковый
Между разными контейнерами: одинаковый
---
Factory:
Внутри одного контейнера: разный
Между разными контейнерами: разный

🎯 Сравнение жизненных циклов

ТипВнутри одного контейнераМежду разными контейнерамиКогда использовать
Scoped ⭐Один объектРазные объектыОбработка запросов, пользовательские сессии
SingletonОдин объектОдин объектКонфигурация, подключения к БД, кеши
FactoryРазные объектыРазные объектыStateless-сервисы, DTO, временные данные

⚠️ Важные замечания

  1. Scoped по умолчанию - если не указан другой тип, используется Scoped
  2. Конфликты приоритетов - нельзя указать один класс одновременно как Singleton и Factory
  3. Производительность - Factory создаёт наибольшую нагрузку, Singleton - наименьшую
  4. Потокобезопасность - Singleton должен быть потокобезопасным в многопоточных средах

🚀 Пример для долгоживущего приложения

<?php
new \Cekta\DI\Compiler(
    containers: [
        HttpController::class,
        UserRepository::class,
        EmailService::class,
    ],
    singletons: [
        Database::class,           // Одно подключение
        RedisCache::class,         // Общий кеш
        Config::class,             // Конфигурация
    ],
    factories: [
        HttpRequest::class,        // Новый для каждого запроса
        UserSession::class,        // Новый для каждого пользователя
    ],
);

Правильное управление жизненным циклом позволяет:

  • Экономить ресурсы (Singleton)
  • Изолировать данные (Scoped)
  • Предотвращать утечки памяти (Factory)
  • Легко масштабировать приложение