# Logger in router.php - How to

**URL:** <https://discourse.slimframework.com/t/logger-in-router-php-how-to/5773>\
**Category:** Questions\
**Created:** [December 9, 2023, 9:57pm UTC](https://discourse.slimframework.com/t/logger-in-router-php-how-to/5773 "2023-12-09T21:57:47Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sinithparanga](https://avatars.discourse-cdn.com/v4/letter/s/a87d85/32.png) [@Sinithparanga](https://discourse.slimframework.com/u/Sinithparanga)\
**Post date:** [December 9, 2023, 9:57pm UTC](https://discourse.slimframework.com/t/logger-in-router-php-how-to/5773/1 "2023-12-09T21:57:47Z")

</div>

Hello,

there has been a lot of time questions on how to use logger (Monolit) in the router.php file, that comes out the box when running slim from Docker, under shinsenter/slim:latest image.

The answers on the web are sometimes confusing and sometimes pointing to different versions. After reading and doing some trial and error, here is my fast and dirty solution to this problem.

```auto
<?php

declare(strict_types=1);

use App\Application\Actions\DB\DB;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
use Slim\Interfaces\RouteCollectorProxyInterface as Group;
use Psr\Log\LoggerInterface;

return function (App $app) {

    $container = $app->getContainer();
    $logger = $container->get(LoggerInterface::class);

    $app->get('/', function (Request $request, Response $response) use ($logger) {
        $response->getBody()->write('Hello world!');

        $logger->info("/ GET was called.");

        return $response;
    });

```

when using RouteCollectorProxyInterface as $group, you can use this:

```auto
<?php

declare(strict_types=1);

use App\Application\Actions\DB\DB;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
use Slim\Interfaces\RouteCollectorProxyInterface as Group;
use Psr\Log\LoggerInterface;

return function (App $app) {

    $app->group('/api', function (Group $group) use ($app) {

        $container = $app->getContainer();
        $logger = $container->get(LoggerInterface::class);

        $group->options('/{routes:.*}', function (Request $request, Response $response) {
            // CORS Pre-Flight OPTIONS Request Handler
            return $response;
        });

        $group->get('/', function (Request $request, Response $response) use ($logger) {
            $response->getBody()->write('Hello world!');

            $logger->info("/api/ GET was called");

            return $response;
        });

```

I just hope it helps someone, as it took me some time to figure this out.

---

<div class="post-metadata">

**Author:** ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)\
**Post date:** [December 10, 2023, 10:24am UTC](https://discourse.slimframework.com/t/logger-in-router-php-how-to/5773/2 "2023-12-10T10:24:09Z")

</div>

Thanks for sharing this. Note that it is also possible to fetch dependencies directly within the route callback.

```php
$app->get('/', function (Request $request, Response $response) {
    $response->getBody()->write('Hello world!');

    $logger = $this->get(LoggerInterface::class);
    $logger->info("/ GET was called.");

    return $response;
});

```

---

<div class="post-metadata">

**Author:** ![Sinithparanga](https://avatars.discourse-cdn.com/v4/letter/s/a87d85/32.png) [@Sinithparanga](https://discourse.slimframework.com/u/Sinithparanga)\
**Post date:** [March 2, 2024, 8:09am UTC](https://discourse.slimframework.com/t/logger-in-router-php-how-to/5773/3 "2024-03-02T08:09:37Z")

</div>

> [@Sinithparanga](#):
>
> `use Slim\App;`

Hi,  
sorry to coming to this after some months, but is there a way to call loggerInterface from a PHPMailer Support Class, like presented in this post: [PHPMailer Example](https://discourse.slimframework.com/t/phpmailer-in-slim4-project/4287/5)?

I tried your initial injection, and it didn’t work. I must say, that this injections stuff is not very intuitive to me.

Thx

---

<div class="post-metadata">

**Author:** ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)\
**Post date:** [March 2, 2024, 12:36pm UTC](https://discourse.slimframework.com/t/logger-in-router-php-how-to/5773/4 "2024-03-02T12:36:18Z")

</div>

> I tried your initial injection, and it didn’t work.

Sorry to hear that. Could you share more details?

> I must say, that this injections stuff is not very intuitive to me.

The concept of dependency injection is to declare all required classes and interfaces within the class constructor. The DI container will then create and inject these objects. It’s a straightforward and efficient way to manage object dependencies.

Using functions (closures) as routing handlers means that you cannot benefit from the concept of DI. The non-class based approach (closures as routing handler) can become unmaintainable in the long run as you have to manually create, wire, and pass everything together.

---

<div class="post-metadata">

**Author:** ![Sinithparanga](https://avatars.discourse-cdn.com/v4/letter/s/a87d85/32.png) [@Sinithparanga](https://discourse.slimframework.com/u/Sinithparanga)\
**Post date:** [March 3, 2024, 11:17am UTC](https://discourse.slimframework.com/t/logger-in-router-php-how-to/5773/5 "2024-03-03T11:17:44Z")

</div>

Hi, thanks for taking the time.

Here is what I tried:

```auto
<?php

namespace App\Application\Actions\Support;

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
use Psr\Log\LoggerInterface;
use Slim\App;

class Mailer
{
    private $host;
    private $username;
    private $password;
    private $port;

    private $from_email;
    private $from_name;

    private $mail;
    private $logger;

    public function __construct()
    {
        $this->mail = new PHPMailer(true);
        $this->logger = new LoggerInterface();
        $this->logger->info("mail was initialiazed");
    }

```

The error here is: “Cannot instantiate interface Psr\Log\LoggerInterface”, which makes sense, I guess.

I also tried this:

```auto
    [...]

    public function __construct()
    {
        $this->mail = new PHPMailer(true);
        $this->logger = $this->get(LoggerInterface::class);
        $this->logger->info("/ GET was called.");
    }

```

Here the msg is: Call to undefined method App\Application\Actions\Support\Mailer::get(), which also makes sense.

> The DI container will then create and inject these objects.

When you say inject, do you mean initialize it in the background and make them available? Are they then treated as static classes overall? and who is the ‘parent’ that manages the DI, is it Slim\App? If you have other sources or code that I can look at, you can also point me to that.

---

<div class="post-metadata">

**Author:** ![Sinithparanga](https://avatars.discourse-cdn.com/v4/letter/s/a87d85/32.png) [@Sinithparanga](https://discourse.slimframework.com/u/Sinithparanga)\
**Post date:** [March 3, 2024, 11:22am UTC](https://discourse.slimframework.com/t/logger-in-router-php-how-to/5773/6 "2024-03-03T11:22:16Z")

</div>

Ok, what ended up working, but I would like to know if this is SlimPHP Best Practice is this:

```auto
// routes.php
$container = $app->getContainer();
$logger = $container->get(LoggerInterface::
...
$mail = new Mailer($logger);

// Mailer.php
private LoggerInterface $logger;
public function __construct(LoggerInterface $_logger)
{
   $this->mail = new PHPMailer(true);
   $this->logger = $_logger;
   $this->logger->debug("Mailer Contructor was called.");
}

```

Which I guess is DI on constructor level… I have always done this, but just today learned that this is DI.

Is this correct and intended?

---

<div class="post-metadata">

**Author:** ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)\
**Post date:** [March 3, 2024, 12:03pm UTC](https://discourse.slimframework.com/t/logger-in-router-php-how-to/5773/7 "2024-03-03T12:03:50Z")

</div>

The DI container itself also acts as a “factory” that can create these objects either automatically (autowiring) or manually using factoring definitions (plain functions).

In your case I would recommend to create a DI container definition for `Psr\Log\LoggerInterface::class` and `PHPMailer::class`.

See here: [PHP-DI - The Dependency Injection Container for humans](https://php-di.org/doc/php-definitions.html#factories)

```php
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;

return [
    LoggerInterface:class => function (ContainerInterface $container) {
        return new Logger(...);
    },

    PHPMailer::class => function (ContainerInterface $container) {
        $mailer = new PHPMailer(...);
        // ...
        return $mailer;
    }),
];

```

Note that the PHPMailer is now “shared”. So when you need to send multiple mails at once, I would recommend to implement a custom **MailerFactory** instead.

Then just declare these dependencies within a Service class when needed:

```php
final class MyService
{
    private LoggerInterface $logger;
    private PHPMailer $mailer;

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

    // your business logic
}

```

Here you can find more information:

- [Slim 4 - Tutorial | Daniel Opitz - Blog](https://odan.github.io/2019/11/05/slim4-tutorial.html#di-container) (Slim Tutorial)
- [PHP-DI - The Dependency Injection Container for humans](https://php-di.org/doc/autowiring.html)
