在静态上下文中使用 log4php

发布于 2024-11-07 15:17:59 字数 838 浏览 0 评论 0原文

我目前正在从我们自己的专有日志记录解决方案迁移到 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();

但这似乎也太大了。那么,有什么建议吗?

I'm currently in the process of moving from our own proprietary logging solution to log4php.
We use a lot of classes with only static methods in our project. The documentation defines the basic use case like:

class MyClass {
   private $logger;

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

But I can't use that, cause I need $logger to be available in a static context as well. Making $logger static as well doesn't help either, because the constructor for my class is never called (as all its members are static).
The documentation tells me to use a static initializer for that member then. But then I would have to remember to call that for all classes I use. And that seems too error-prone.

So I came up with this:

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();

But that seems like too much overhead as well. So, any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

还如梦归 2024-11-14 15:17:59

我想出了一种效果很好的解决方案,但需要 $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

I came up with one solution that works quite well but requires $logger to be public.

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 ) );
}

This I only have to define the $logger property once per class and run my initialization code once (I guess after the require_once section of the entry point of my application).

The performance impact of that code is negligible, especially since it is only run once (compared to my initial solution). This is what I measured inside a VirtualBox VM on an Intel Core2 Q9450 @2.66GHz:

10000 iterations for 157 classes completed in 2.6794s. Average per iteration: 0.00026794s
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文