DI: как инстанциировать реализацию интерфейса с кастомным значением параметра конструктора?

Юзаю php-di 6.0.10

В DI конфиге указана имплементация интерфейса:

\App\Writer\WriterInterface::class => DI\get(\App\Writer\Text::class)


Реализация имеет вот такой конструктор:

class TextWriter implements WriterInterface {
// ... 
public function __construct(Settings $settings, DataConverter $dataConverter, string $filePath)
{
    $this->init($filePath);
    $this->settings = $settings;
    $this->dataConverter = $dataConverter;
}


В своём приложении я хочу инстанциировать Writer с динамическим значением $filePath в конструкторе:

$this->container->make(WriterInterface::class, ['filePath' => $this->getFilePath()]);


Но вылазит такая ошибка:

DI\Definition\Exception\InvalidDefinition: Entry "App\Writer\Text" cannot be resolved: Parameter $filePath of __construct() has no value defined or guessable Full definition: Object ( class = App\Writer\Text lazy = false __construct( $settings = get(App\Settings) $dataConverter = get(App\DataConverter) $filePath = #UNDEFINED# )


Что не так? Работает только если я явно передаю App\Writer\Text вметод make(). Но мне нужно указывать именно интерфейс, а не реализацию.
  • Вопрос задан
  • 219 просмотров
Решения вопроса 2
Maksclub
@Maksclub Куратор тега PHP
maksfedorov.ru
Используйте фабрику:

- В конфиге контейнера
// регайте ваш интерфейс, но ссылаясь на метод фабрики,
// которая и произведет ваш сервис
\App\Writer\WriterInterface::class => DI\factory('\App\Writer\TextWriterFactory::create'),

- Код фабрики:
class TextWriterFactory implements WriterFactoryInterface
{
    public function __construct(Settings $settings, DataConverter $dataConverter)
    {
        $this->settings = $settings;
        $this->dataConverter = $dataConverter;
    }

    public function create(string $filePath): WriterInterface
    {
        return new TextWriter($this->settings, $this->dataConverter, $filePath);
    }
}


Источник: php-di.org/doc/php-definitions.html#factories
Ответ написан
Audiophile
@Audiophile Автор вопроса
То что хотел сделать, не получилось - для интерфейсов make() параметры в конструктор не передаёт.
Вынес выбор реализации в спец класс (по входному параметру и карте) - дальше инстанциирую уже не интерфейс, а реализацию, и параметр работает.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы