Home > Net >  Symfony Messenger Injection Doctrine
Symfony Messenger Injection Doctrine

Time:11-06

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 App\Service\Messenger;

use Symfony\Component\Messenger\MessageBusInterface;

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 App\Service\Messenger;

class ServiceMethodCallMessageLowPriority extends ServiceMethodCallMessage
{

}

My ServiceMethodCallMessage

<?php

namespace App\Service\Messenger;

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 App\Service\Messenger;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

#[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 App\Service;

use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

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
    App\Service\Messenger\ServiceMethodCallHandler:
        arguments: ['%kernel.project_dir%/config']

    App\Service\SendInBlueService:
        class: App\Service\SendInBlueService
        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

CodePudding user response:

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.

CodePudding user response:

Could you please change this:

    App\Service\SendInBlueService:
        class: App\Service\SendInBlueService
        arguments: ['%env(SEND_IN_BLUE_API_KEY)%','@doctrine.orm.entity_manager']

By this:

    App\Service\SendInBlueService:
        arguments:
            $SEND_IN_BLUE_API_KEY: '%env(SEND_IN_BLUE_API_KEY)%'

As services are autowired.

  • Related