Исключение объектов при печати переменных print_r () в пользовательском логгере - PullRequest
4 голосов
/ 31 мая 2011

У меня есть Logger-Class, который регистрирует все. Объекты будут зарегистрированы с print_r в удобочитаемом состоянии. Моя проблема в том, что у меня есть большой MVC-объект. Каждый раз, когда возникает исключение или ошибка, объект MVC также будет печататься в журнале с помощью print_r. В результате получается очень длинный лог-файл, который не очень удобен для чтения.

Я пытался установить метод __toString() для моего MVC-класса, но это не работает. Я также получаю полный MVC-объект в журнале. MVC является синглтоном и на него ссылаются все объекты. Так что просто исключить объект до его появления в print_r не так просто.

Есть ли способ исключить объекты из print_r?

Мои методы:

LOG-класс errorHandler-Method:

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-Class exceptionHandler-Method:

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-Method:

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

Таким образом, это спокойствие в коде привело к регистрации Var $mvc с помощью print_r через errorHandler в LOG-Class.

Вывод для меня: не используйте переменные на больших объектах-одиночках и не используйте unset (), если переменная больше не нужна.

Ответы [ 5 ]

2 голосов
/ 31 мая 2011

__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);
1 голос
/ 31 мая 2011

Вы можете обернуть print_r своей собственной функцией, которая проверяет, включают ли предоставленные данные какие-либо объекты, используя функцию is_object().Точно так же вы можете использовать is_a(), если хотите исключить определенные классы объектов.

0 голосов
/ 31 мая 2011

Если вы можете изменить класс Logger, вы можете проверить класс перед тем, как его напечатать:

if(!($var instanceof HeavyMVCObject)){
    print_r($var);
}
0 голосов
/ 31 мая 2011
if (is_object( $foo ))
{
  print_r( $foo->__toString() );
} else {
  print_r( $foo );
}
0 голосов
/ 31 мая 2011

в качестве html-решения вы можете использовать:

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

для лучшего отображения вашего файла журнала.Я отображаю файлы журнала таким образом.

...