Как передать динамические значения в контейнер в Symfony 5

#php #symfony

#php #symfony

Вопрос:

Как передать динамическую переменную из контроллера в службу? Я хочу управлять некоторыми параметрами в конструкторе моего сервиса, которые зависят от значения json. Мой сервис принимает два параметра в конструкции: сервис и переменную с JSON.

Для первого я передал его непосредственно в service.yaml. Для второго у меня есть некоторые трудности.

В контроллере я получаю из API JSON. Но в этом json это может быть null.

 class IndexController extends AbstractController
{
    /**
     * @Route("/converter-hl7", name="converter", methods={"POST"})
     */

    public function index(Request $request, $myjson = null) {
        $myjson = $request->getContent();

        global $kernel;
        $converter = $kernel->getContainer()->get('app.converter');
        $xml = $converter->outputXML();

        $response = new Response($xml);
        $response->headers->set('Content-Type', 'xml');

        return $response;

    }
 

Я сохраняю JSON в своем файле .env, MYJSON=null.
Это мой service.yaml

 # This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.

# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:

services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

    # makes classes in src/ available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    App:
        resource: '../src/'
        exclude:
            - '../src/DependencyInjection/'
            - '../src/Entity/'
            - '../src/Kernel.php'
            - '../src/Tests/'

    # controllers are imported separately to make sure services can be injected
    # as action arguments even if you don't extend any base controller class
    AppController:
        resource: '../src/Controller/'
        tags: ['controller.service_arguments']

    # add more service definitions when explicit configuration is needed
    # please note that last definitions always *replace* previous ones
    # explicitly configure the service

    app.error:
        class: AppServiceError
        public: true
        autowire: true

    app.converter:
        class: AppServiceConverterHl7Refacto
        public: true
        autowire: true
        arguments:
            $error: '@app.error'
            $json: '%env(MYJSON)'

            
 

Итак, в моем сервисе вызывается ConverterHl7Refacto.php , у меня есть два параметра в конструкторе. Я хотел бы управлять параметрами, если json пуст или отсутствует. Если я выполняю dd() из $json, я получаю ‘%env (MYJSON)’ вместо JSON. Почему?

 class ConverterHl7Refacto
{
    private $ricetta;
    private $identificativiDocumento;
    private $codiceDocumento;
    private $infoDocumento;
    private $assistiti;
    private $partecipanti;
    private $relatedDoc;
    private $structuredBody;
    private $root;
    private $error;




    public function __construct(string $json,Error $error) {
        $this->error = $error;
        
        if ($json){
            $this->ricetta = new Ricetta(json_decode($json));
            $this->root = new Root();
            $this->identificativiDocumento = new Identificativi();
            $this->codiceDocumento = new CodiceDocumento($this->ricetta);
            $this->infoDocumento = new InfoDocumento($this->ricetta);
            $this->assistiti = new Assistiti($this->ricetta);
            $this->partecipanti = new Partecipanti($this->ricetta);
            $this->relatedDoc = new RelatedDocument($this->ricetta);
            $this->structuredBody = new StructuredBody($this->ricetta);
        }
    }
 

Комментарии:

1. ‘%env(MYJSON)’ подразумевает, что у вас есть переменная среды с именем MYJSON, поэтому для нее не будет установлено значение $myjson . По сути, контейнер не поддерживает то, что вы пытаетесь сделать. Добавьте метод init в свой конвертер и вызовите его с помощью $myjson . Или, возможно, лучшее решение, создайте себе фабрику конвертеров. Не по теме, но вы также должны вводить свой конвертер, а не извлекать его непосредственно из контейнера.

2. Можете ли вы привести мне пример этой фабрики конвертеров? И, в функции init, что он должен вернуть? Спасибо!

Ответ №1:

Ничего особенно сложного в концепции factory. Фабрика в основном используется для создания экземпляра заданного типа. Я не тестировал следующий код, поэтому приношу извинения за опечатки:

 class Error {}
class Converter {
    public function __construct(string $json, Error $error)
    {
        // Whatever
        ...
class ConverterFactory {
    private $error;
    public function __construct(Error $error) {
        $this->error = $error;
    }
    public function create(string $json) : Converter {
        return new Converter($json,$this->error);
    }
}
class MyController {
    public function action(ConverterFactory $converterFactory)
    {
        $json = $request->getContent();
        $converter = $converterFactory->create($json);
 

Вам нужно будет исключить ваш класс Converter из autowire в ваших сервисах.файл yaml. Но это должно быть все, что вам нужно. Нет необходимости явно определять такие вещи, как app.converter, поскольку autowire позаботится обо всем этом.

Комментарии:

1. он выдает мне эту ошибку: контроллер «App Controller IndexController::index()» требует, чтобы вы указали значение для аргумента «$ json». Либо аргумент имеет значение null, и значение null не было предоставлено, значение по умолчанию не было предоставлено, либо после этого аргумента есть необязательный аргумент.

2. Я изменил код контроллера. Вам действительно стоит взглянуть на документы и привести несколько примеров, чтобы увидеть, как все работает.