skip to Main Content

I need help for my project.
I try to inject Entity Manager inside my service (SendInBlueService) call with messenger, but DependencyInjection can’t find doctrine.orm.entity_manager.

My test route

#[Route('api/testSendInBlue', name: 'testsendinblue')]
public function testMessenger(AsyncMethodService $asyncMethodService): Response
{
    $asyncMethodService->async_low_priority(
        SendInBlueService::class,
        'confirmationMail',
        [
            $this->getUser()->getId()
        ]
    );

    return new Response('Test OK');
}

My AsyncMethodService

<?php

namespace AppServiceMessenger;

use SymfonyComponentMessengerMessageBusInterface;

class AsyncMethodService
{
    private MessageBusInterface $messageBus;

    public function __construct(MessageBusInterface $messageBus)
    {
        $this->messageBus = $messageBus;
    }

    public function async_low_priority(string $serviceName, string $methodName,array $params = [])
    {
        $this->messageBus->dispatch(new ServiceMethodCallMessageLowPriority(
            $serviceName,
            $methodName,
            $params
            )
        );
    }
    public function async_medium_priority(string $serviceName, string $methodName,array $params = [])
    {
        $this->messageBus->dispatch(new ServiceMethodCallMessageMediumPriority(
            $serviceName,
            $methodName,
            $params
        )
        );
    }
    public function async_high_priority(string $serviceName, string $methodName,array $params = [])
    {
        $this->messageBus->dispatch(new ServiceMethodCallMessageHighPriority(
            $serviceName,
            $methodName,
            $params
        ));
    }
}

My ServiceMethodCallMessageLowPriority exactly same for High and Medium

<?php

namespace AppServiceMessenger;

class ServiceMethodCallMessageLowPriority extends ServiceMethodCallMessage
{

}

My ServiceMethodCallMessage

<?php

namespace AppServiceMessenger;

class ServiceMethodCallMessage
{
    private string $serviceName;
    private string $methodName;
    private array $params;

    public function __construct(string $serviceName, string $methodName, array $params = [])
    {
        $this->serviceName = $serviceName;
        $this->methodName = $methodName;
        $this->params = $params;
    }

    /**
     * @return string
     */
    public function getServiceName(): string
    {
        return $this->serviceName;
    }

    /**
     * @return string
     */
    public function getMethodName(): string
    {
        return $this->methodName;
    }

    /**
     * @return array
     */
    public function getParams(): array
    {
        return $this->params;
    }
}

My MessengerHandle

<?php

namespace AppServiceMessenger;

use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentDependencyInjectionContainerBuilder;
use SymfonyComponentMessengerAttributeAsMessageHandler;
use SymfonyComponentConfigFileLocator;
use SymfonyComponentDependencyInjectionLoaderYamlFileLoader;

#[AsMessageHandler]
class ServiceMethodCallHandler extends AbstractController
{
    private string $path;

    public function __construct(string $path)
    {
        $this->path = $path;
    }

    public function __invoke(
        ServiceMethodCallMessageLowPriority |
        ServiceMethodCallMessageMediumPriority |
        ServiceMethodCallMessageHighPriority  $message
    )
    {
        $containerBuilder = new ContainerBuilder();
        $loader = new YamlFileLoader($containerBuilder, new FileLocator($this->path));
        $loader->load('services.yaml');

        $callable = [
            $containerBuilder->get($message->getServiceName()),
            $message->getMethodName()
        ];
        call_user_func_array($callable,$message->getParams());
    }
}

My Service Send In Blue

<?php

namespace AppService;

use AppEntityUser;
use DoctrineORMEntityManagerInterface;
use SymfonyComponentConfigFileLocator;
use SymfonyComponentDependencyInjectionContainerBuilder;
use SymfonyComponentDependencyInjectionLoaderYamlFileLoader;

class SendInBlueService
{
    private string $SEND_IN_BLUE_API_KEY;
    private EntityManagerInterface $entityManager;

    public function __construct(
        string $SEND_IN_BLUE_API_KEY,
        EntityManagerInterface $entityManager
    )
    {
        $this->SEND_IN_BLUE_API_KEY = $SEND_IN_BLUE_API_KEY;
        $this->entityManager = $entityManager;
    }

    public function confirmationMail(int $userId)
    {
        dd($this->entityManager);
        $user = $this->entityManager->getRepository(User::class)->find($userId);
        dd($user);
    }

}

My config/services.yaml

parameters:
    SEND_IN_BLUE_API_KEY: '%env(SEND_IN_BLUE_API_KEY)%'

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.

    App:
        resource: '../src/'
        exclude:
            - '../src/Entity/'
            - '../src/Kernel.php'
            - '../src/DependencyInjection/'

    #    Messenger Declaration Service
    AppServiceMessengerServiceMethodCallHandler:
        arguments: ['%kernel.project_dir%/config']

    AppServiceSendInBlueService:
        class: AppServiceSendInBlueService
        arguments: ['%env(SEND_IN_BLUE_API_KEY)%','@doctrine.orm.entity_manager']

And for finish my error:

enter image description here

I try get EntityManager with ContainerBuilder inside my service,
But i have a same error.

I think i have a problem because messenger use other kernel instance, and inside this instance, the DependencyInjection don’t have load all bundles.

If someone has an idea.
Thanks you

3

Answers


  1. Chosen as BEST ANSWER

    I found issue,

    My first try on my ServiceMethodCallHandler is :

    <?php
    
    namespace AppServiceMessenger;
    
    use PsrContainerContainerInterface;
    use SymfonyComponentMessengerAttributeAsMessageHandler;
    
    #[AsMessageHandler]
    class ServiceMethodCallHandler
    {
        public function __construct(ContainerInterface $container)
        {
            $this->container = $container;
        }
    
        public function __invoke(
            ServiceMethodCallMessageLowPriority |
            ServiceMethodCallMessageMediumPriority |
            ServiceMethodCallMessageHighPriority  $message
        )
        {
            $callable = [
                $this->container->get($message->getServiceName()),
                $message->getMethodName()
            ];
            call_user_func_array($callable,$message->getParams());
        }
    }
    

    But ive got error. enter image description here

    I finish by build new container inside __invoke method. This build i can call my service but i create another error. With @Cerad message i understood that it was a mistake to create a new Container inside invoke. I restart to my first error.

    I finish by find issue with add public inside service.yaml

    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/Entity/'
                - '../src/Kernel.php'
                - '../src/DependencyInjection/'
    
        #    Messenger Declaration Service
        AppServiceMessengerServiceMethodCallHandler:
            arguments: ['@service_container']
    
        AppServiceSendInBlueService:
            public: true
            class: AppServiceSendInBlueService
            arguments: ['@doctrine.orm.entity_manager','%env(SEND_IN_BLUE_API_KEY)%']
    

    Thank you all


  2. I found auto-wiring / dependency injection via using aliases always very confusing (what is visible and what is hidden, blahblah), and have usually opted to use default parameter bindings instead:

    https://symfony.com/doc/current/service_container.html#binding-arguments-by-name-or-type

    Using this method, you would remove the service from the services.yaml entirely (since all parameters will be known) and instead use

    services:
        _defaults:
            bind: 
                string $SEND_IN_BLUE_API_KEY: '%env(SEND_IN_BLUE_API_KEY)%'
    

    If in fact the doctrine bundle is missing from your loaded kernel, you have to find a way to add it.

    Login or Signup to reply.
  3. Could you please change this:

        AppServiceSendInBlueService:
            class: AppServiceSendInBlueService
            arguments: ['%env(SEND_IN_BLUE_API_KEY)%','@doctrine.orm.entity_manager']
    

    By this:

        AppServiceSendInBlueService:
            arguments:
                $SEND_IN_BLUE_API_KEY: '%env(SEND_IN_BLUE_API_KEY)%'
    

    As services are autowired.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search