admin管理员组

文章数量:1334876

I want to call service method dynamically with autowired parameters

for now I do as followed :

$result = call_user_func_array([$myService,"myMethod"],[$entityManager,$tranlator]);

The problem is that sometimes the service method needs other parameters than $entityManager and $translator.

I would like to call $myservice without specifying parameters (like i would to with dependency injection).

my method looks like this :

 public function myMethod(EntityManagerInterface $em,TranslatorInterface $translator)
 { 
  return "toto"; 
 }

I tried another way to load my method services directly from the class constructor but since it extends another class I have to call all parents services. that not really clean

class LicensePackController extends MainController
{

    
    public function __construct(TranslatorInterface $translator, SystemTools $systemTools, KernelInterface $kernel, Permissions $permissions, ManagerRegistry $doctrine, RequestStack $requestStack, RouterInterface $router)
    {
        parent::__construct($translator, $systemTools, $kernel, $permissions, $doctrine, $requestStack, $router);
    }
}

I want to call service method dynamically with autowired parameters

for now I do as followed :

$result = call_user_func_array([$myService,"myMethod"],[$entityManager,$tranlator]);

The problem is that sometimes the service method needs other parameters than $entityManager and $translator.

I would like to call $myservice without specifying parameters (like i would to with dependency injection).

my method looks like this :

 public function myMethod(EntityManagerInterface $em,TranslatorInterface $translator)
 { 
  return "toto"; 
 }

I tried another way to load my method services directly from the class constructor but since it extends another class I have to call all parents services. that not really clean

class LicensePackController extends MainController
{

    
    public function __construct(TranslatorInterface $translator, SystemTools $systemTools, KernelInterface $kernel, Permissions $permissions, ManagerRegistry $doctrine, RequestStack $requestStack, RouterInterface $router)
    {
        parent::__construct($translator, $systemTools, $kernel, $permissions, $doctrine, $requestStack, $router);
    }
}
Share Improve this question edited Nov 21, 2024 at 8:48 Chopchop asked Nov 20, 2024 at 18:43 ChopchopChopchop 2,94920 silver badges38 bronze badges 4
  • 2 Probably going to be disappointed. Lots of folks look at how Symfony calls controller action methods with what looks like dependency injection. But there is a lot of code behind that capability and it only works because only the Symfony kernel ever calls the action methods directly. It is interesting to look at how Symfony manages to do that but it is not something that PHP supports directly and not something that can be expanded. – Cerad Commented Nov 20, 2024 at 19:08
  • 2 Explain the other problem you are trying to solve and maybe we could suggest a better alternative that won't require auto wiring outside the service container. – Victor Vasiloi Commented Nov 20, 2024 at 21:37
  • @victor-vasiloi you're right there's other problems behind. I edited my question – Chopchop Commented Nov 21, 2024 at 8:53
  • Looks like you are making custom request controllers? If so then looking at how the Symfony base controller class uses a service locator might be helpful. – Cerad Commented Nov 21, 2024 at 13:07
Add a comment  | 

2 Answers 2

Reset to default 1

Original answer

You should use constructor injection in your service:

class YourService
{
    public function __construct(
        private EntityManagerInterface $em,
        private TranslatorInterface $translator,
    ) {
    }

    public function myMethod()
    {
        $this->em->getRepository(Entity::class);

        // ...

        return "toto"; 
    }
}

Answer for updated question

If you can't use constructor injection you can use setter injection and #[Required] attribute to Container automatically call it after service initialisation. Try this code:

#[Required]
public function setInjectedService(InjectedService $service): void
{
    $this->service = $service;
}

After further investigation there's maybe a solution using "AutowireMethodOf Attribute" but I can't test it since I am in symfony 6.4 for now

$result = $this->container->get($myService)->$myMethod();

https://symfony/blog/new-in-symfony-7-1-new-dependency-injection-attributes

public function myMethod(
 #[AutowireCallable(service: EntityManagerInterface)],
#[AutowireCallable(service: TranslatorInterface )]
)
 { 
  return "toto"; 
 }

本文标签: phpCall method with autowired parameterStack Overflow