5

According to your sample on Github you inject the logger interface in the constructor with default value of NULL.

<?php

use Psr\Log\LoggerInterface;

class Foo
{
    private $logger;

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

    public function doSomething()
    {
        if ($this->logger) {
            $this->logger->info('Doing work');
        }

        // do something useful
    }
}

Expressing that something has a Logger you can implement Psr\Log\LoggerAwareInterface and the Psr\Log\LoggerAwareTrait.

Rebuilding the sample code it would look something like this

<?php

use Psr\Log\LoggerInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;

class Foo implements  LoggerAwareInterface
{
    use LoggerAwareTrait;

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

    public function doSomething()
    {
        if ($this->logger) {
            $this->logger->info('Doing work');
        }

        // do something useful
    }
}

Thats fine and working but if i would do this

<?php

use Psr\Log\LoggerInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;

class Foo implements  LoggerAwareInterface
{
    use LoggerAwareTrait;

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

    public function doSomething()
    {
        if ($this->logger) {
            $this->logger->info('Doing work');
        }

        // do something useful
    }
}

it would end up in a must be an instance of Psr\Log\LoggerInterface, null given error because there is no NULL default value on the method declaration in the interface. Of course this error can be prevented by guarding with an if or passing a NullLogger but this is very weird.

Beeing able to pass an optional Logger instance in the constructor would make me think that i can alter the instance later by setting the Logger to a value of NULL. Of course this is a sample code but lets look at the problem

  public function __construct(LoggerInterface $logger = null);

  public function setLogger(LoggerInterface $logger);

So basically i can pass a NULL reference into the constructor but i would not be possible to call the setter because NULL is not allowed. It would have been much better if the Psr\Log\LoggerAwareInterface would look like this

<?php

namespace Psr\Log;

/**
 * Describes a logger-aware instance.
 */
interface LoggerAwareInterface
{
    /**
     * Sets a logger instance on the object.
     *
     * @param LoggerInterface $logger
     *
     * @return void
     */
    public function setLogger(LoggerInterface $logger = null);
}

So please tell me the background to this decision ?

Jay
  • 1,035
  • 2
  • 11
  • 22
  • 1
    Shouldn't this be an issue on their Github repo instead of a question on SO? Specially since you start it with: _"According to **your** sample..."_ – M. Eriksson Nov 03 '16 at 12:32
  • 1
    http://www.php-fig.org/faqs/ says ask questions on SO – Jay Nov 03 '16 at 12:53
  • You mean this: _"While there are many user groups and forums dedicated to **providing general PHP support**, the FIG is not one of them..."_? You're question isn't about general PHP support, but rather a very specific question which only the developers can answer (since you ask about the background for a decision they made.) – M. Eriksson Nov 03 '16 at 13:07
  • 1
    Indeed but i thought it would be of interrest for a wider group of people – Jay Nov 03 '16 at 13:17

1 Answers1

2

I think you are mixing many questions here.

The example usage https://github.com/php-fig/log#usage shows how you can use a psr/log implementation in your application. It does it correctly too.

So the next question is about usage of LoggerAwareInterface and setLogger method via the LoggerAwareTrait

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

If your constructor is accepting null, you should not call the setLogger method. The setLogger method can only accepts LoggerInterface and it doesn't accidentally need to set the logger object to null itself.

Lets say the signature was as setLogger($logger = null). Now if you call setLogger() as in example below you can see the logger will be reset to null.

$logger = new SomePSR-3Logger();
$foo = new Foo($logger);
$foo->setLogger();

If you want to implement a PSR-3 logger you should consider reading : https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md

Hope that helps.

Thank you.

Hari K T
  • 4,174
  • 3
  • 32
  • 51