How to inject a service in another service in Symfony?

I am trying to use the logging service in another service in order to trouble shoot that service.

My config.yml looks like this:

services:
    userbundle_service:
        class:        Main\UserBundle\Controller\UserBundleService
        arguments: [@security.context]

    log_handler:
        class: %monolog.handler.stream.class%
        arguments: [ %kernel.logs_dir%/%kernel.environment%.jini.log ]


    logger:
        class: %monolog.logger.class%
        arguments: [ jini ]
        calls: [ [pushHandler, [@log_handler]] ]

This works fine in controllers etc. however I get no out put when I use it in other services.

Any tips?

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

You pass service id as argument to constructor or setter of a service.

Assuming your other service is the userbundle_service:

userbundle_service:
    class:        Main\UserBundle\Controller\UserBundleService
    arguments: [@security.context, @logger]

Now Logger is passed to UserBundleService constructor provided you properly update it, e.G.

protected $securityContext;
protected $logger;

public function __construct(SecurityContextInterface $securityContext, Logger $logger)
{
    $this->securityContext = $securityContext;
    $this->logger = $logger;
}

Solution 2

For Symfony 3.3, 4.x, 5.x and above, the easiest solution is to use Dependency Injection

You can directly inject the service into another service, (say MainService)

// AppBundle/Services/MainService.php
// 'serviceName' is the service we want to inject
public function __construct(\AppBundle\Services\serviceName $injectedService)  {
    $this->injectedService = $injectedService;
}

Then simply, use the injected service in any method of the MainService as

// AppBundle/Services/MainService.php
public function mainServiceMethod() {
    $this->injectedService->doSomething();
}

And viola! You can access any function of the Injected Service!

For older versions of Symfony where autowiring does not exist –

// services.yml
services:
    \AppBundle\Services\MainService:
        arguments: ['@injectedService']

Solution 3

More versatile option, is to once create a trait for the class you would want to be injected. For instance:

Traits/SomeServiceTrait.php

Trait SomeServiceTrait
{
    protected SomeService $someService;

    /**
     * @param SomeService $someService
     * @required
     */
    public function setSomeService(SomeService $someService): void
    {
        $this->someService = $someService;
    }
}

And where you need some service:

class AnyClassThatNeedsSomeService
{
    use SomeServiceTrait;

    public function getSomethingFromSomeService()
    {
        return $this->someService->something();
    }
}

The class will autoload due to @required annotation. This generaly makes it much faster to implement when you want to inject services into numerous classes (like event handlers).

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply