0

PHP で巨大なオブジェクトを適切にデバッグするために、ヘルパー クラス Utility::error_log() に静的メソッドがあります。メソッドとそのヘルパー メソッド 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 ... )

$data = var_export($data,true)error_log() の長さの制限であると言う前に、問題なく結果を 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)ですか??

4

1 に答える 1

0

答えは、印刷できない文字です。オブジェクトから配列への変換、およびそれらのさまざまなプロパティから文字列への変換では、これらの文字列には表示されない非印刷制御文字が含まれていますが、存在するため、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);

$message をエラー ログに送信する前に呼び出されます。これにより、多くの非印刷文字が削除され、削除されたことがわかった他の preg の多くの文字が保持されます。必要な場合に備えて:

\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 = ø ù ú û ü ý þ ÿ

最終的に、一部の機能を別の場所で使用できるように分離するためにいくつかの追加の書き直しが行われましたが、最終的な解決策はシンプルです。

編集: さらに調べてみると、これはより具体的にバグ #64439 - "\0 により error_log 文字列が切り捨てられる" に関連しているようです。

\0 (または \x00 または \x0) は NULL 文字であり、上記の特定のケースでは、オブジェクトを配列としてキャストした結果であり、Key 値を返しますNULL.classname.NULL.propname

于 2013-04-05T19:15:47.140 に答える