【问题标题】:Using log4php in a static context在静态上下文中使用 log4php
【发布时间】:2011-08-26 07:40:17
【问题描述】:

我目前正在从我们自己的专有日志记录解决方案迁移到 log4php。
我们在项目中使用了很多只有静态方法的类。该文档定义了基本用例,例如:

class MyClass {
   private $logger;

   public function __construct() {
       $this->logger = Logger::getLogger(__CLASS__);
       $this->logger->debug('currently in constructor');
   }
} 

但我不能使用它,因为我还需要 $logger 在静态上下文中可用。将$logger 设为静态也无济于事,因为我的类的构造函数永远不会被调用(因为它的所有成员都是静态的)。
文档告诉我然后为该成员使用静态初始化程序。但是我必须记住为我使用的所有类调用它。这似乎太容易出错了。

所以我想出了这个:

class Foo {
  private static $logger = null;
  private static function logger() {
    if( null == self::$logger ) self::$logger = Logger::getLogger( __CLASS__ );
    return self::$logger;
  }

  public static function bar() {
    self::logger()->debug( "test" );
  }
}

Foo::bar();

但这似乎也有太多的开销。那么,有什么建议吗?

【问题讨论】:

    标签: php logging log4php


    【解决方案1】:

    我想出了一个效果很好但需要 $logger 公开的解决方案。

    class Foo {
      public static $logger = null;
    
      public static function bar() {
        self::$logger->debug( "test" );
      }
    }
    
    $loggerName = "logger";
    // Iterate over all declared classes
    $classes = get_declared_classes();
    foreach( $classes as $class ) {
      $reflection = new ReflectionClass( $class );
    
      // If the class is internally defined by PHP or has no property called "logger", skip it.
      if( $reflection->isInternal() || !$reflection->hasProperty( $loggerName ) ) continue;
    
      // Get information regarding the "logger" property of this class.
      $property = new ReflectionProperty( $class, $loggerName );
    
      // If the "logger" property is not static or not public, then it is not the one we are interested in. Skip this class.
      if( !$property->isStatic() || !$property->isPublic() ) continue;
    
      // Initialize the logger for this class.
      $reflection->setStaticPropertyValue( $loggerName, Logger::getLogger( $class ) );
    }
    

    我只需要为每个类定义一次$logger 属性并运行一次我的初始化代码(我猜在我的应用程序入口点的require_once 部分之后)。

    该代码对性能的影响可以忽略不计,尤其是因为它只运行一次(与我最初的解决方案相比)。这是我在 Intel Core2 Q9450 @2.66GHz 上的 VirtualBox VM 内测得的:

    10000 iterations for 157 classes completed in 2.6794s. Average per iteration: 0.00026794s
    

    【讨论】:

    • 您的方法有一个很大的缺点:在自动加载的环境中,这将不起作用,因为类仅在第一次使用后才声明。此外,将记录器推送到某个地方是一种糟糕的编码模式。最好让班级要求一个并注入它。
    猜你喜欢
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 2011-09-10
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多