Pergunta

Atualmente estou em processo de mudança de nosso próprio log de solução para log4php.
Nós usamos um monte de aulas com apenas métodos estáticos em nosso projeto.A documentação que define o básico do caso de uso como:

class MyClass {
   private $logger;

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

Mas eu não posso usar isso, porque eu preciso $logger para estar disponível em um contexto estático também.Fazendo $logger estático, como também não ajuda, porque o construtor para a minha turma nunca é chamado (como todos os seus membros são estáticas).
A documentação diz-me a usar um inicializador estático para que o membro em seguida.Mas então eu teria que lembrar de chamada para todas as classes que eu uso.E que parece muito propenso a erro.

Então eu vim com este:

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

Mas que parece muito sobrecarga de bem.Então, alguma sugestão?

Foi útil?

Solução

Eu vim com uma solução que funciona muito bem, mas exige $logger para ser público.

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

Isso só tenho a definir a $logger propriedade de uma vez por classe e execute o meu código de inicialização de uma vez (eu acho que depois que o require_once seção do ponto de entrada do aplicativo).

O impacto no desempenho do que o código é desprezível, especialmente desde que ele é executado apenas uma vez (em comparação com a minha solução inicial).Isso é o que eu medidos dentro de uma VM VirtualBox em um Intel Core2 Q9450 @2.66 GHz:

10000 iterations for 157 classes completed in 2.6794s. Average per iteration: 0.00026794s
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top