duanpa2143 2013-04-05 19:15
浏览 41
已采纳

print_r()到PHP error_log()不起作用。 (非打印字符)

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 = "
".$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;
}

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
(
    [

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 ... )

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 ... )

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)??

  • 写回答

1条回答 默认 最新

  • doukun1450 2013-04-05 19:15
    关注

    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('/(?!
    )[[:cntrl:]]+/','',$data);
    

    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.

    EDIT: Upon further review, it seems this is more specifically related to Bug #64439 - "\0 causes error_log strings to be truncated".

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 LiBeAs的带隙等于0.997eV,计算阴离子的N和P
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 来真人,不要ai!matlab有关常微分方程的问题求解决,
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿
  • ¥15 回答4f系统的像差计算