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

PSR Log - Why no NULL default value for LoggerAwareInterface and LoggerAwareTrait

根据您在 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 来防止此错误,但这很奇怪。

能够在构造函数中传递一个可选的 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);
}

所以请告诉我这个决定的背景?

我认为你在这里混淆了很多问题。

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

所以下一个问题是关于LoggerAwareInterface and setLogger method via the LoggerAwareTrait

的用法
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

希望对您有所帮助。

谢谢。