4

根据您在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
    }
}

表示某些东西有一个你可以实现的 LoggerPsr\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 或传递 a 来防止此错误,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);
}

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

4

1 回答 1

2

我想你在这里混合了很多问题。

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

所以下一个问题是关于通过LoggerAwareTrait使用LoggerAwareInterfacesetLogger方法

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

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

可以说签名为setLogger($logger = null)。现在,如果您setLogger()按照下面的示例调用,您可以看到记录器将被重置为空。

$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

希望有帮助。

谢谢你。

于 2016-11-03T14:18:31.157 回答