Skip to content
Advertisement

How to pass dynamic values to container in Symfony 5

How passing a dynamic variable from controller to a service? I want manage some istance in the constructor of my service that depend by json value. My service take two parameters in the construct: a service and a variable with the JSON.

For the first one, i have passed it directly in the service.yaml. For the second one, i have some difficult.

In the controller, i get from a API the JSON. But this json it can be 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;

    }

I stock the JSON in my .env file, MYJSON=null. This is my 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)'

            

So, in my service called ConverterHl7Refacto.php, i have the two parameters in the constructor. I would like manage the istances if the json is empty or non. If i do a dd() of $json, i get ‘%env(MYJSON)’ instead JSON. Why?

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);
        }
    }

Advertisement

Answer

Nothing particularly tricky about the factory concept. A factory is basically used to create an instance of a given type. I did not test the following code so apologies for typos:

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);

You will need to exclude your Converter class from autowire in your services.yaml file. But that should be all you need. No need to explicitly define things like app.converter as autowire will take care of all that.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement