Search code examples
phpsingletonstandardsstrict

Strict standards warning: Singleton implementation with PHP


I have created a logger as a singleton for my PHP application with Zend framework.

Implementation is pretty straight-forward:

class Logger
{
    protected static $_logger;

    private function __construct()
    {
        // initialize logger
        $writer = new Zend_Log_Writer_Stream(LOG_PATH);
        $this->_logger = new Zend_Log($writer);
    }

    public static function getLogger()
    {
        if (null === self::$_logger)
        {
            self::$_logger = new self();
        }        
        return self::$_logger;
    }

    public static function Log($message, $logType)
    {
        if ($logType <= LOG_MAX)
        {
            $logger = self::getLogger();        
            $logger->_logger->log($message, $logType);
        }
    }
}

To ad an entry to the log, I just call static method: Logger::Log('message', Zend_Log::ERR);

Logger works as supposed to, but since I have upgraded my PHP version to 5.4.3 I get an error:

Strict standards: Accessing static property Logger::$_logger as non static in Z:\Software\PHP\EA Game\application\classes\Logger.php on line 28

Line 28 is in function __construct(): $this->_logger = new Zend_Log($writer);

I can always disable E_STRICT, but it is not a preferable option. I would like to implement Singleton pattern without getting Strict standards warning.

I would be grateful if some could point me in the right direction to implementing Singleton pattern without getting String standards warning.

EDIT: I used jValdrons advice and replaced $this->_logger to self::$_logger. I still was getting strict standards warning and I changed Log function to be as follows:

public static function Log($message, $logType)
{
    if ($logType <= LOG_MAX)
    {
        self::getLogger()->log($message, $logType);
    }
}

But now I have another problem.

Code does not throw Strict standards warning, but it does not works as supposed to.

I have 2 separate loggers, 1 for application and 1 for crons. Basically it's just the same code: 2 static variables:

protected static $_logger;
protected static $_cronLogger;

constructor initializes both of them:

private function __construct()
{
    // initialize all loggers
    $writer = new Zend_Log_Writer_Stream(LOG_PATH);
    self::$_logger = new Zend_Log($writer);

    $writerCron = new Zend_Log_Writer_Stream(CRON_LOG_PATH);
    self::$_cronLogger = new Zend_Log($writerCron);
}

and 2 methods GetCronLogger() and LogCron():

public static function getCronLogger()
{
if (null === self::$_cronLogger)
    {
    self::$_cronLogger = new self();
}        
return self::$_cronLogger;
}


public static function LogCron($message, $logType)
{
    if ($logType <= CRON_LOG_MAX)
    {
        self::getCronLogger()->log($message, $logType);
    }
}

But now self::getCronLogger()->log($message, $logType); calls my method Log(), not Zend_log->log() and it will always add records to my main logger, not crons logger.

Am I missing something or calling something in incorrect way?


Solution

  • You're accessing the logger using $this->logger, which is not a static way to access it. Since it's a static variable, you got to use self:: just like you did got getLogger, so:

    private function __construct()
    {
        // initialize logger
        $writer = new Zend_Log_Writer_Stream(LOG_PATH);
        self::$_logger = new Zend_Log($writer);
    }