PHP:如何为特征中的属性提供非原始默认值?

时间:2014-09-11 09:53:11

标签: php dependency-injection traits

有没有办法为特征中的属性提供默认对象?

trait myTrait{
  private $foo = 0; // works
  private $bar = new stdClass(); // doesn't work.
}

我知道将具体对象实例化为默认值(由于高耦合)似乎是一种糟糕的编码风格。这里的想法是为可选的依赖项提供NullObject

示例用例

一个更好的例子(我正在考虑的那个):

使用特征进行记录,并将PSR-3 Logging的默认NullLogger默认为默认属性:

trait LoggerTrait{
  /**
    * @var Psr\Log\LoggerInterface
    */
  protected $logger;

  public function setLogger(Psr\Log\LoggerInterface $logger){
    $this->logger = $logger;
  }
}

class Foo{
  use LoggerTrait;

  public function __construct(){
    $this->setLogger(new Psr\Log\NullLogger()); // I would like to avoid this line as I'd need to duplicate it in every class I'm using the LoggerTrait.
  }

  public function doStuff(){
    $this->logger->info("Yey flexible logging with no overhead!");
  }

}

这有效,但我必须在每个使用该特征的类中明确设置NullLogger,我想避免这种“代码重复”。

PS:我相信有人会提出记录器也可以通过DI容器插入。这是事实,但不是真的有必要。有关一些赞成/反对论点,请参阅此blog post + comments:)

1 个答案:

答案 0 :(得分:1)

解决此问题的常用方法是在类中使用getter,即使该类拥有该属性。

trait LoggerTrait{
    /**
     * @var Psr\Log\LoggerInterface
     */
    protected $logger;

    public function setLogger(Psr\Log\LoggerInterface $logger){
        $this->logger = $logger;
    }

    public function getLogger()
    {
        if(null === $this->logger) {
            $this->logger = new Psr\Log\NullLogger();
        }

        return $this->logger;
    }
}

这样,默认对象甚至不会被实例化,直到需要它为止。

class Foo{
    use LoggerTrait;

    public function doStuff(){
        $this->getLogger()->info("Yey flexible logging with no overhead!");
    }
}