Intereting Posts
CakePHP Забыли пароль? Как преобразовать xml в массив в php? Удалить .php из URL mysql_query () ожидает, что параметр 1 будет строкой, ресурс указан Как получить длину самой длинной строки в массиве настроить несколько баз данных в zf2 Laravel Scheme Builder добавляет auto_increment ко всем целочисленным полям, которые не позволяют как получить разрешение экрана пользователя с помощью PHP Наследование PHP и видимость защищенного элемента Использование конфигурации apache для указания директории PHP include для каждого сайта Неустранимая ошибка: нельзя использовать объект типа mysqli_result В PHP лучший способ обеспечить текущий рабочий каталог такой же, как скрипт, при использовании CLI У меня есть класс с 14 статическими методами и 4 статическими свойствами – это плохо? множественные входы codeigniter в таблице Регулярное выражение, как сделать регулярное выражение вторым / ** в качестве отправной точки

Ошибка Print_r () в PHP error_log () не работает. (непечатаемые символы)

У меня есть статический метод в вспомогательном классе Utility :: error_log (), который помогает нам изящно отлаживать HUGE-объекты в PHP. Этот метод и его вспомогательный метод Utility :: toArray () приведены ниже:

static function error_log($message, $data=null, $max=2) { if(is_array($data) || is_object($data)) $data = print_r(self::toArray($data, $max),true); if(is_array($message) || is_object($message)) $message = print_r(self::toArray($message, $max),true); if(!empty($data)) $data = "\n".$data; if (!strstr($message, PHP_EOL)) $message = str_pad(" ".$message." ", 50,'=',STR_PAD_BOTH); error_log($message.$data); } static function toArray($object, $max = 2, $current = 0) { if($current > $max) return ucfirst(gettype($object)).'( ... )'; $current++; $return = array(); foreach((array) $object as $key => $data) if (is_object($data)) $return[$key] = self::toArray($data, $max, $current); elseif (is_array($data)) $return[$key] = self::toArray($data, $max, $current); else $return[$key] = $data; return $return; } 

Теперь, на что можно немного взглянуть, но суть в том, что toArray делает ОГРОМНЫЙ объект (много рекурсивных) порядков меньшей величины и возвращает все свойства в виде массивов или строк. Намного легче работать с … Идея заключается в том, что print_r($array,true) затем делает массив строкой, и мы заносим ее в журнал.

Однако это не работает должным образом. Результат:

 [05-Apr-2013 05:29:00] ==================================== PERSISTING SUITS & SHIRTS =================================== Array ( [ 

И тогда ничего, где, когда я вызываю print_r($data) и печатаю в браузер, я получаю:

 Array ( [BRS\PageBundle\Entity\Pageroot_folder_name] => Pages [id] => 43 [title] => Suits & Shirts [depth_title] => Suits & Shirts [description] => ( ... AND SO ON ... ) 

Прежде чем вы скажете, что это ограничение длины error_log (), я упомянул, что могу успешно $data = var_export($data,true) и отправить результат в error_log () без проблем:

 [05-Apr-2013 06:00:08] ==================================== PERSISTING SUITS & SHIRTS =================================== array ( '' . "\0" . 'BRS\\PageBundle\\Entity\\Page' . "\0" . 'root_folder_name' => 'Pages', 'id' => 43, 'title' => 'Suits & Shirts', 'depth_title' => 'Suits & Shirts', 'description' => ( ... AND SO ON ... ) 

В чем проблема? Почему он работает с var_export($data,true) и print_r($data,false) , но не с print_r($data,true) ?

Ответ – непечатаемые символы. При преобразовании объектов в массивы и их различных свойствах в строки эти строки содержат непечатаемые управляющие символы, которые мы никогда не видим, но по мере их существования прерываем PHP error_log() .

Решение довольно простое, но важное:

 $data= preg_replace('/[^\x0A\x20-\x7E\xC0-\xD6\xD8-\xF6\xF8-\xFF]/','',$data); // Or to preserve extended characters, use the below expression. // Mind you many of these still may not display correctly in logs. $data= preg_replace('/(?!\n)[[:cntrl:]]+/','',$data); 

Вызывается перед отправкой сообщения $ в журнал ошибок, это удаляет много непечатаемых символов, сохраняя много символов других прегов, которые я нашел удаленными. На всякий случай, если они вам понадобятся:

 \x0A = [newline] \x20-\x7E = [space] ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ ABCDEFGHIJKLMNOPQRSTU VWXYZ [ \ ] ^ _ ` abcdefghijklmnopqrstu vwxyz { | } ~ \xC0-\xD6 = À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö \xD8-\xF6 = Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö \xF8-\xFF = ø ù ú û ü ý þ ÿ 

В конце концов, была некоторая дополнительная перезапись, чтобы изолировать некоторые функции для использования в другом месте, но окончательное решение так же просто.

EDIT: после дальнейшего рассмотрения, похоже, это более конкретно связано с ошибкой # 64439 – «\ 0 приводит к усечению строк error_log» .

Для тех, кто задается вопросом, \ 0 (или \ x00 или \ x0) является символом NULL, а в конкретном выше случае является результатом литья объекта в виде массива, который возвращает значение ключа NULL.classname.NULL.propname .