Print_r()到PHP error_log()无效. (非打印字符) [英] Print_r() to PHP error_log() not working. (non-printing characters)
问题描述
我在帮助器类Utility :: error_log()中有一个静态方法,可以帮助我们正常地调试PHP中的HUGE对象.该方法及其辅助方法Utility :: toArray()如下:
I have a static method in a helper class Utility::error_log() for helping us gracefully debug HUGE objects in PHP. The method, and it's helper-method Utility::toArray() are below:
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使HUGE对象(许多递归)的大小减小了数量级,并以数组或字符串的形式返回所有属性.使用起来要容易得多...这个想法是print_r($array,true)
然后使数组成为字符串,然后我们将其记录下来.
Now that may be a bit to look at, but the gist is, toArray makes a HUGE object (lots of recursion) orders of a magnitude smaller, and returns all properties as either arrays or strings. Much easier to work with... The idea being that print_r($array,true)
then makes the array a string, and we log it.
但是,这无法正常工作.结果是:
This doesn't work as expected, however. The result is:
[05-Apr-2013 05:29:00] ==================================== PERSISTING SUITS & SHIRTS ===================================
Array
(
[
然后什么都没有,当我调用print_r($data)
并打印到浏览器时,我得到:
And then nothing, where when I call print_r($data)
and print to the browser, I get:
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():
Before you say it is an error_log() length limitation, I will mention that I can successfully $data = var_export($data,true)
and send the result to error_log() with no problems:
[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)
一起使用??
What is the problem? Why does it work with var_export($data,true)
, and print_r($data,false)
, but not with print_r($data,true)
??
推荐答案
答案是不可打印的字符.在将对象转换为数组以及将其各种属性转换为字符串的过程中,这些字符串包含我们从未见过的非打印控制字符,但是当它们存在时,会破坏PHP的error_log()
.
The answer is non-printable characters. In the conversion of Objects to Arrays, and their various Properties to Strings, these Strings contain non-printing control characters that we never see, but as they exist, break PHP's error_log()
.
该解决方案非常简单,但必不可少:
The solution is a rather simple, but essential:
$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);
在将$ message发送到错误日志之前被调用,这会删除许多非打印字符,同时保留许多我发现已删除的其他字符.以防万一您需要它们:
Called before sending the $message to the Error Log, this removes many non-printing characters while preserving many characters other pregs I found removed. Just in case you need them:
\x0A = [newline]
\x20-\x7E = [space] ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
\xC0-\xD6 = À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö
\xD8-\xF6 = Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö
\xF8-\xFF = ø ù ú û ü ý þ ÿ
最后,进行了一些额外的重写以隔离某些功能以供在其他地方使用,但是最终的解决方案很简单.
In the end, there was some additional rewriting to isolate some functionality for use elsewhere, but the ultimate solution is as simple.
经过进一步审查,看来这与错误#64439有关-"\ 0导致error_log要截断的字符串" .
Upon further review, it seems this is more specifically related to Bug #64439 - "\0 causes error_log strings to be truncated".
对于那些想知道的人,\ 0(或\ x00或\ x0)是NULL字符,在上述特殊情况下,是对象转换为数组的结果,该数组返回键值
For those wondering, \0 (or \x00 or \x0) is the NULL character, and in the particular above case, is a result of the Casting of the Object as an Array, which returns a Key value of NULL.classname.NULL.propname
.
这篇关于Print_r()到PHP error_log()无效. (非打印字符)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!