PSR日志 - 为什么LoggerAwareInterface和LoggerAwareTrait没有NULL默认值

时间:2016-11-03 12:16:51

标签: php psr-3

根据您在Github上的示例,您在构造函数中注入了记录器接口,其默认值为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
    }
}

表示某些东西有Logger,您可以实施Psr\Log\LoggerAwareInterfacePsr\Log\LoggerAwareTrait

重建示例代码,它看起来像这样

<?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
    }
}

这很好并且工作但是如果我会这样做

<?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
    }
}

它最终会出现must be an instance of Psr\Log\LoggerInterface, null given错误,因为接口中的方法声明没有NULL默认值。当然,可以通过使用if或NullLogger来防止此错误,但这非常奇怪。

Beeing能够在构造函数中传递可选的Logger实例会让我觉得我可以稍后通过将Logger设置为NULL值来更改实例。当然这是一个示例代码,但让我们看一下问题

  public function __construct(LoggerInterface $logger = null);

  public function setLogger(LoggerInterface $logger);

所以基本上我可以将NULL引用传递给构造函数但是我不可能调用setter因为不允许NULL。如果Psr\Log\LoggerAwareInterface看起来像这样

会好得多
<?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);
}

那么请告诉我这个决定的背景?

1 个答案:

答案 0 :(得分:2)

我认为你在这里混合了许多问题。

示例用法https://github.com/php-fig/log#usage显示了如何在应用程序中使用psr/log实现。它也是正确的。

所以接下来的问题是LoggerAwareInterface

LoggerAwareTraitsetLogger方法的使用
public function __construct(LoggerInterface $logger = null)
{
    $this->setLogger($logger);
}

如果构造函数接受null,则不应调用setLogger方法。 setLogger方法只能接受LoggerInterface,并且不会意外地将记录器对象设置为null。

让我们说签名是setLogger($logger = null)。现在,如果您在下面的示例中调用setLogger(),则可以看到记录器将重置为null。

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

如果您想要实施PSR-3记录器,您应该考虑阅读:https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md

希望有所帮助。

谢谢。