Компоненты Symfony 4.1 - проблемы внедрения зависимостей

Рефакторинг старого приложения на PHP.

Я пытаюсь использовать компонент внедрения зависимостей Symfony для внедрения сервисов в контроллеры (или другие сервисы), но я не знаю, как этого добиться, потому что документация по симфонии более подготовлена ​​для использования фреймворка, чем компонентов фреймворка.

У меня уже есть собственное ядро, контейнер, содержащий все службы и контроллеры (контроллеры уже зарегистрированы как службы). Мои контроллеры расширяют AbstractController из symfony/frameworkbundle. Итак, единственное, что я могу сделать сейчас, это:

Получить службу из контейнера с помощью $this->container->get('service_id'), но если служба в конструкторе будет иметь класс в качестве параметра

public function __constructor(SomeClass $someClass)

то я получаю это исключение:

The "App\V2\Service\TestService" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.

Если я изменю конфигурацию, чтобы сделать все службы общедоступными, то:

Too few arguments to function APP\V2\Service\TestService::__construct(), 0 passed and exactly 1 expected

Я готовлю суть, чтобы лучше понять, о чем я говорю: https://gist.github.com/miedzwin/49bac1cc1d5270d3ba1bfcf700abf864

Может ли кто-нибудь мне немного помочь с реализацией DI с использованием компонентов Symfony (а не фреймворка Symfony)? Достаточно хорошего рабочего примера. Или просто добавьте свои замечания в мою суть, я пытаюсь это исправить.

Как выглядит APP\V2\Service\T estService? Где его зарегистрировать?

Tomas Votruba 09.09.2018 19:11

Кроме того, вы можете упростить свою конфигурацию следующим образом: gist.github.com/TomasVotruba/09af5a9452abaa91b64c15b740d74f2‌ e /…

Tomas Votruba 09.09.2018 19:14

@ TomášVotruba Я не регистрировал сервис, он должен регистрироваться автоматически, т.к. autowire: true. Я обновил суть, чтобы вы могли проверить, как выглядит TestService.php.

miedzwin 10.09.2018 07:52

Хорошо, я внес изменения, как вы сделали в gist (ControllerResolver и ArgumentResolver теперь должны быть общедоступными, иначе я не могу использовать их в классе Framework). Сейчас это выглядит лучше, но теперь у меня есть другие проблемы: 1. Если в конфигурации службы по умолчанию установлен public: true, то службы, которые имеют в конструкторе аргументы скалярного типа (строка, целое число, массив), не могут быть подключены автоматически. Cannot autowire service "APP\V2\Service\API": argument "$facebookUserId" of method "__construct()" has no type-hint, you should configure its value explicitly.

miedzwin 10.09.2018 08:45

2 Если public: false - Controller "APP\V2\Controller\API\SocialNetworkController::loginAction(‌​)" requires that you provide a value for the "$testService" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one. Итак, похоже, служба все еще не введена.

miedzwin 10.09.2018 08:46

Отличная обратная связь! Вы только что дали мне важные элементы. Я постараюсь дать правильный ответ на вашу ситуацию.

Tomas Votruba 10.09.2018 10:52

@ TomášVotruba Я создал репо: github.com/miedzwin/legacy-framework Вы можете проверить, как это работает прямо сейчас. Если есть время, конечно. Может быть, ты быстрее найдешь, что я сделал не так. Спасибо.

miedzwin 21.09.2018 15:29

Хорошо, я в нескольких местах спрашиваю, как с этим справиться, и решение было - собственный преобразователь контроллеров. Любой, кто может проверить, как я это сделал, - проверьте репо из предыдущего сообщения и просмотрите код в теге v0.1.

miedzwin 23.10.2018 15:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
3
8
2 970
2

Ответы 2

https://symfony.com/doc/current/service_container.html#fetching-and-using-services

Вам нужно изменить конфигурацию по умолчанию для вашего сервиса, чтобы сделать его общедоступным:

services:
    _defaults:
        public: true

Но более элегантный способ доступа к сервисам - это внедрить их в действия контроллера:

public function myAction(Request $request, TestService $service)

Автоматическое подключение Symfony 4/5

Судя по вашему вопросу и комментариям, я думаю, что все, что вам нужно сделать, это исправить автоматическую проводку.

В Symfony все просто: автосоединение всех сервисов и параметров, без ручной настройки (если возможно).

Чтобы применить это к вашему примеру, это будет лучшая конфигурация, соответствующая вашим потребностям и Symfony 4:

services:
    _defaults:
        # pass service dependencies to constructors by default
        autowire: true

        # add known tags (for commands, event subscribers etc) by default
        autoconfigure: true
        
        # to make using tests, bin files and another simpler
        public: true

        # autowiring of string/array/int parameters to constructors
        # this fixes cases like "argument "$facebookUserId" of method "__construct()" has no type-hint, you should configure its value explicitly"
        bind:
            # $constructorVariableName: %parameter% in config
            $facebookUserId: '%facebook_user_id%'

    APP\V2\:
        resource: '../src/app/V2/*'
        exclude: '../src/app/V2/{Script, Trait}'

    # symfony services - you still have to setup 3rd paryt services manually
    Symfony\Component\DependencyInjection\ParameterBag\ContainerBag:
        arguments:
            - '@service_container'
    # ...

Где продолжить чтение

Другие вопросы по теме