Logging from inside a repository in Symfony

symfony logging
symfony log to stdout
symfony log channels
monolog levels
symfony log exception
symfony/monolog-bundle
symfony not logging
psr\log\loggerinterface

I'm tracing a weird error in a Symfony 2 app and I'd like to know if there's a way to print log messages from a Repository PHP file. For example:

class OrderEntityRepository extends EntityRepository
{
    /**
    * 
    * @param mixed $filter
    * @return type
    */ 
    public function findByCriteria($filter) {
        [...]

        /* I'D LIKE TO LOG SOME VARIABLES FROM HERE */
    }
}

I've tried using error_log() but nothing happens.

Is this possible? Thanks in advance,

It's possible but it's usually not a good practice. The good thing to do is to send back the Repository result to your Controller or Service and you log from them an error or something else.

But if you still want to do it, Repository are like services (when you implements ServiceEntityRepository see this slide for more information). If you want to log something specific inside you have to inject the LoggerInterface into your Repository configuration (like you do with service).

In your service.yml (or xml) if you don't use autowire:

Your\Repository:
    arguments: ['@logger']

In your repository class:

/**
 * @var LoggerInterface
 */
protected $logger;


public function __construct(LoggerInterface $logger)
{
    $this->logger = $logger;
}

Logging (Symfony Docs), Depending on the verbosity setting, log messages will be sent to the OutputInterface You can rely on the logger to use this dependency inside a command:  Logging: Symfony comes with a minimalist PSR-3 logger: Logger. In conformance with the twelve-factor app methodology, it sends messages starting from the WARNING level to stderr.

On symfony 3.8 I have

class BlahRepository extends ServiceEntityRepository
{

    /* @var ContainerInterface $container */
    private $container;

    /* @var LoggerInterface $logger */
    private $logger;

    public function __construct(RegistryInterface $registry, ContainerInterface $container, LoggerInterface $logger)
    {
        parent::__construct($registry, Blah::class);
        $this->container = $container;
        $this->logger = $logger;
    }
}

and I am able to use $this->logger->info("text")

I think the trick may be extending ServiceEntityRepository

Using the Logger (The Console Component, You should probably avoid putting business logic (even logging) inside entity model. As for the repositories, the way you described is the right one. Dependency injection with autowiring is super easy since Symfony 3.3.Yet on my mentoring I still meet service locators. Mostly due to traditional registration of Doctrine repositories.

In order to use dependency injection for Doctrine entity repositories, you can create a custom RepositoryFactory. Tested on Symfony 3.4.

<?php
namespace AppBundle\Doctrine;

use Doctrine\Common\Persistence\ObjectRepository;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Repository\DefaultRepositoryFactory;
use Doctrine\ORM\Repository\RepositoryFactory as RepositoryFactoryInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;

class RepositoryFactory implements RepositoryFactoryInterface, LoggerAwareInterface
{
    /** @var DefaultRepositoryFactory */
    protected $defaultRepositoryFactory;

    /** @var LoggerInterface */
    private $logger;

    /**
     * @required (for autowiring)
     * @param LoggerInterface $logger (Monolog will be the default one)
     */
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }

    /**
     * @see Configuration::getRepositoryFactory()
     */
    public function __construct()
    {
        $this->defaultRepositoryFactory = new DefaultRepositoryFactory();
    }

    /**
     * Gets the repository for an entity class.
     *
     * @param EntityManagerInterface $entityManager
     * @param string $entityName The name of the entity.
     * @return ObjectRepository
     */
    public function getRepository(EntityManagerInterface $entityManager, $entityName): ObjectRepository
    {
        $repository = $this->defaultRepositoryFactory->getRepository($entityManager, $entityName);

        if ($repository instanceof LoggerAwareInterface && $this->logger !== null) {
            $repository->setLogger($this->logger);
        }

        return $repository;
    }
}

Declare it in Doctrine configuration.

# app/config.yml
doctrine:
    # ...
    orm:
        repository_factory: AppBundle\Doctrine\RepositoryFactory

And finally, make your repository class implement LoggerAwareInterface.

class OrderEntityRepository extends EntityRepository implements LoggerAwareInterface
{
    /** @var LoggerInterface */
    private $logger;

    /**
     * @param LoggerInterface $logger
     */
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }

    /**
     * @param mixed $filter
     * @return type
     */
    public function findByCriteria($filter) {
        //[...]
        $this->logger->alert('message');
    }
}

You can also make a LoggerAwareTrait trait to spare yourself some code duplication.

Logging events to database in Symfony, Mostly due to traditional registration of Doctrine repositories. container (events, collections, autowiring, automated registration, logging etc.). Hi, I'm new to symfony and I'm having some issues with log messages. Can you please tell me how can I log info mesages from inside a Form Class. $logger = $this->get

Correct way to log from Entities and Repositories in Symfony2, Symfony 4 > And then we can say, $articles = $repository->findAll() : create a custom query, you can do that by creating a custom method inside of this class. All about Entity Repositories. we get the repository for the class: you can do that by creating a custom method inside of this class.

How to use Repository with Doctrine as Service in Symfony, Copy the app.yaml file from this repository into the root of your project and For your Symfony application to integrate with Logging and Error  The Console component comes with a standalone logger complying with the PSR-3 standard. Depending on the verbosity setting, log messages will be sent to the OutputInterface instance passed as a parameter to the constructor. The logger does not have any external dependency except psr/log . This is useful for console

All about Entity Repositories > Doctrine & the Database , The spatie/laravel-activitylog package provides easy to use functions to log the activities of the users of your app. It can also automatically log model events. The​  Symfony provides all the tools you need to use databases in your applications thanks to Doctrine, the best set of PHP libraries to work with databases. These tools support relational databases like MySQL and PostgreSQL and also NoSQL databases like MongoDB. Databases are a broad topic, so the documentation is divided in three articles:

Comments
  • I'm not sure, but you would like to try with PHPUnit
  • Setup a logger service for the repository and then call it ($this->logger->info($my, $vars)). Or use VarDumper's dump(). If you have print_r or whatnot and nothing's happening, likely it's not getting called.
  • Hi, I've modified the files Resources/config/service.yml and the repository class file following your instructions, and I get this error: Catchable fatal error: Argument 1 passed to Master\StoreBundle\Entity\Repository\OrderEntityRepository::__construct() must be an instance of Master\StoreBundle\Entity\Repository\LoggerInterface, instance of Doctrine\ORM\EntityManager given. Do I have to change anything else to make it work?
  • @Fel Basic problem is that original question did not make it clear that you were using Doctrine's repository. So this answer is less that useful. Just lookup how to use a factory to create the repository service and how to use setters to inject the logger.
  • @Cerad I've read the comment you left for my post but you decided to delete it but I am very much interested in what you had to say to my question above. It is because if I miss something I would like to know. Thanks
  • Thanks everyone for your comments. I couldn't make it work but I found a workaround using echo and printing what I need to the HTML output. It doesn't solve the question, but I'll keep on investigating and I'll update it when I find something relevant.