Search code examples
phpsymfonyservicedoctrine

Symfony static/global Logger with doctrine access


maybe i try the impossible thing, but i try so archive a logging system where i can log anywhere with something like Logger::info('some info') or plain LogInfo(...).

So no pre-initialisation with new .. or as parameter/injection (have to us it in some functions with "dynamic" count of parameters). I need to use inside a controller/command and outside in smaller custom made classes and functions, called by some way by the controllers/commands but not extending any containers.

for example i use the MessageGenerator Example from the Symfony Docs

// srcMessageGenerator.php

namespace App\Library\Util;

use Doctrine\ORM\EntityManagerInterface;

class MessageGenerator
{
    private $em;
    public function setEM(EntityManagerInterface $em){
        $this->em = $em;
        var_dump('a');
    }

    public function getHappyMessage(){
        var_dump($this->em);
        $messages = [
            'You did it! You updated the system! Amazing!',
            'That was one of the coolest updates I\'ve seen all day!',
            'Great work! Keep going!',
        ];
    
        $index = array_rand($messages);
    
        return $messages[$index];
    }
}

I already tried to define it as service

# config/services.yaml
services:
    App\Library\Util\MessageGenerator:
        arguments: ['@doctrine.orm.entity_manager']
        public: true

problem: i have to inject it to every function i wanna use it - not possible

i tried use it as an static function - services can't be static

i tried to isolate it as static function without beeing a service, but then i don't know how to get the config/package/doctrine settings depending on my env.

i have looked into monolog too, but here is the same problem, i cant use it without declaration outside a controller/command.

anyone have a hint how i can access the default (env based) doctrine connection, or how i can use a service inside/outside a controller/command without declaring it (static like) and giving the entity manager to it.

(a solution to second way would be lovely, so i can "upgrade" to monolog some day using the same solution)


Solution

  • You can use Injecting Services/Config into a Service in Symfony by passing your service to the function in your controller.

    Your service:

    class MessageGeneratorService
    {
        private $em;
    
        public function __construct(EntityManagerInterface $em){
            $this->em = $em;
        }
        public function getHappyMessage(){
        // the job
        }
    }
    

    In an other service:

    class MyService
    {
        private $messageGeneratorService;
    
        public __construct(MessageGeneratorService $mGService) {
            $this->messageGeneratorService = $mGService
        }
    
        // You can use this service like you use MessageGeneratorService
        public makeMeHappy() {
            $messageGeneratorService->getHappyMessage();
        }
    }
    

    In a controller:

    class MyController
    {
        /**
         * @Route("/example", name="page_example")
         */
        public index(MessageGeneratorService $mGService) {
            $mGService->getHappyMessage(); // Now, you can use it
            return $this->render('example/index.html.twig');
        }
    }
    

    Now, you can use an instance of MessageGeneratorService in a controller or in a service:

    The container will automatically know to pass the logger service when instantiating the MessageGenerator