在自定义记录器中打印变量时排除对象


Excluding objects when print_r()ing variables in a custom logger

我有Logger class,它记录所有内容。对象将使用print_r记录到可读状态。我的问题是我有一个很大的MVC对象。每次发生异常或错误时,MVC对象也会通过print_r打印在日志中。这导致了一个非常长的日志文件,读取起来并不友好。

我试图为我的MVC类设置一个__toString()方法,但这不起作用。我还在日志中得到了完整的MVC对象。MVC是一个Singleton,在每个对象上都被引用。因此,在Object进入print_r之前简单地排除它并不是那么容易。

有没有办法从print_r中排除对象?

我的方法:

LOG类错误处理程序方法:

public static function errorHandler($errno, $errstr, $errfile, $errline, $vars) {
                //If @ is set, don't do anything!
                if(error_reporting() === 0) {
                        return;
                }
                //Get StackTrace with low memory usage ;)
                $e = new Exception();
                $stackStr = $e->getTraceAsString();
                //Build ErrorMessage for Log
                $message =      'File: '.$errfile.' - L: '.$errline."'n".
                                'Code: '.$errno."'n".
                                'Message: '.$errstr."'n".
                                'Vars: '.print_r($vars, true)."'n".
                                'Stacktrace: '.$stackStr;
                self::error($message);
        }

LOG类异常处理程序方法:

public static function exceptionHandler(Exception $e) {
        $message =      get_class($e).': '.$e->getMessage()."'n".
                        'File: '.$e->getFile().' - L: '.$e->getLine()."'n".
                        'Code: '.$e->getCode()."'n".
                        'Message: '.$e->getMessage()."'n".
                        'Stacktrace: '.$e->getTraceAsString();
        self::error($message);
}

LOG类错误方法:

public static function error($data, $file='system.log') {
        $config = Megaira_PropertyConfiguration::getInstance();
        switch($config->get('LOG_MODE')) {
                case'DEEPDEBUG':
                case'ERROR':
                case'WARNING':
                case'INFO':
                case'DEBUG':
                        self::writeToLog('ERROR', $data, $file);
                        break;
        }
}

LOG类writeToLog方法:

private static function writeToLog($mode='', $text='', $file=''){
        if(!is_string($text) && !is_numeric($text)) {
                $text = print_r($text, true);
        }
        $config = Megaira_PropertyConfiguration::getInstance();
        if(!$config->get('LOGGINGACTIVE')) { return; }
        self::writeLineToFile($mode, $text, $file);
}

设置错误和异常处理程序:

        //Set Error and Exception Handler
        set_error_handler(array(new LOG(), 'errorHandler'));
        set_exception_handler(array(new LOG(), 'exceptionHandler'));

感谢

一些测试:

public static function print_r_filtered($object, $ret=false) {
                $filtered = array(
                        'Megaira_MVC'
                );
                $text = print_r($object, true);
                foreach($filtered as $filter) {
                        $search = '#('.$filter.''sObject)'n('s+)').*?'n'2')'n#s';
                        $replace = "$1";
                        $text = preg_replace($search, $replace, $text);
                }
                if($ret)
                        return $text;
                echo $text;
        }

不起作用。也许RegEx失败了?

解决方案:

这是一个设计缺陷。errorHandler正在记录错误发生地使用的所有对象。因此,在index.php中有以下代码:

$mvc = Megaira_MVC::getInstance();

因此,这种代码的平静通过LOG类中的errorHandler生成了带有print_r的Var $mvc的日志记录。

对我来说,结论是:不要在大型Singleton对象上使用Variables,如果不再需要Var,也不要使用unset()。

__toString()在对象被强制转换为字符串时被调用。你可以试试

$objectString = method_exists($object, '__toString')
              ? (string) $object
              : print_r($object, true);

使用is_object()来确定一个值是否为对象。

$string = !is_object($value) || method_exists($value, '__toString')
        ? (string) $value
        : print_r($value, true);

您可以使用自己的函数包装print_r,该函数使用is_object()函数检查所提供的数据是否包括任何对象。类似地,如果只想排除某些类的对象,则可以使用is_a()

作为一个html解决方案,您可以使用:

<pre><?=print_r(log_content);?></pre>

以便更好地显示日志文件。我以这种方式显示日志文件。

if (is_object( $foo ))
{
  print_r( $foo->__toString() );
} else {
  print_r( $foo );
}

如果可以更改Logger类,则可以在打印前检查该类:

if(!($var instanceof HeavyMVCObject)){
    print_r($var);
}