【问题标题】:custom var_dump output for my class我的班级的自定义 var_dump 输出
【发布时间】:2013-05-12 16:46:23
【问题描述】:

是否可以覆盖自定义类的 var_dump 输出? 我想要这样的东西:

class MyClass{
    public $foo;
    public $bar;
    //pseudo-code
    public function __dump($foo, $bar)
    {
        return 'Foo:$foo, bar:$bar';
    }
}

var_dump(array($instanceOfMyClass));
//it should output this:
array(1) {
  [0] =>
  class MyClass#1 (2) {
    Foo:valueOfFoo, bar:valueOfBar
  }
}

我知道我可以使用一些 3rd-party var_dump 替代品,但我想在我的库项目中自定义 var_dump 的行为。

谢谢。

【问题讨论】:

    标签: php var-dump


    【解决方案1】:

    PHP 5.6.0+中,可以使用__debugInfo()魔术函数自定义var_dump()的输出。

    array __debugInfo ( void )

    此方法由var_dump() 在转储对象以获取应显示的属性时调用。如果该方法未在对象上定义,则将显示所有公共、受保护和私有属性。

    此功能是在 PHP 5.6.0 中添加的。

    示例:

    class MyDateTime{
        public $year, $month, $day, $hour, $minute, $second;
        public function __debugInfo() {
            return array(
                'date' => $this->year . "-" . $this->month . "-" . $this->day,
                'time' => sprintf("%02d:%02d:%02d", $this->hour, $this->minute, $this->second),
            );
        }
    }
    
    $dt = new MyDateTime();
    $dt->year = 2014; $dt->month = 9; $dt->day = 20;
    $dt->hour = 16; $dt->minute = 2; $dt->second = 41;
    var_dump($dt);
    

    PHP 5.6.0 的输出:

    object(MyDateTime)#1 (2) {
      ["date"]=>
      string(9) "2014-9-20"
      ["time"]=>
      string(8) "16:02:41"
    }
    

    PHP 5.0.0 - 5.5.16 的输出:

    object(MyDateTime)#1 (6) {
      ["year"]=>
      int(2014)
      ["month"]=>
      int(9)
      ["day"]=>
      int(20)
      ["hour"]=>
      int(16)
      ["minute"]=>
      int(2)
      ["second"]=>
      int(41)
    }
    

    注意事项:

    1. __debugInfo() 必须返回 array。我在 PHP 5.6.0 上返回 string 时出错:

      致命错误:__debuginfo() 必须在第 15 行的 /somepath/somefile.php 中返回一个数组

    2. 它似乎也适用于 print_r(),尽管这似乎没有在任何地方记录。

    【讨论】:

      【解决方案2】:

      为此,您可以使用 ReflectionClass 函数并构建您自己的函数来获取您需要的信息。

      http://php.net/manual/de/reflectionclass.tostring.php
      http://php.net/manual/en/book.reflection.php

      【讨论】:

      • 谢谢,但不影响 var_dump 的输出。 var_dump 输出是硬连线的,还是可以为特定类定制?
      • 你不能覆盖 php 函数。您可以构建自己的 var_dump 函数并获取您需要的所有信息。
      • 我不想重写 PHP 函数,我想为特定类自定义其行为。问题是是否可以覆盖特定类的 var_dump 行为,即通过魔术方法。
      【解决方案3】:

      您不能覆盖核心 PHP 函数。

      您可以在对象中添加函数 __toString():

      class myClass {
          public function __toString(){
              // custom var_dump() content here then output it
          }
      }
      
      $myClass = new myClass();
      
      echo $myClass;
      

      【讨论】:

      • 谢谢,但我知道如何使用 __toString。我想在转储通用 PHP 类的复杂结构时简化 var_dump 输出,以及它们之间的一些类可以以更简单的方式转储。
      【解决方案4】:

      重写 var_dump 结果没有意义,你可以使用 toString() 魔术方法

      class MyClass{
      public $foo;
      public $bar;
      public function test(){}
      public function __toString()
       {
          $vars="Variables:";
          foreach(get_class_vars(__CLASS__) as $name => $value) $vars.="<br> $name : {$this->{$name}}".gettype($this->{$name});
          return __CLASS__.':<br>'.$vars.'<br>Methods:<br>'.implode('<br>',get_class_methods(__CLASS__));
       }
      }
      
      $lol = new MyClass();
      $lol->foo = 10;
      $lol->bar = 'asd';
      
       echo $lol;
      

      例如HERE

      【讨论】:

      • 知道如何使用toString。关键是,我有复杂的对象结构(PHP 数组和其他类),部分结构是我可以简化的类对象。我想用 var_dump 转储整个这个结构,并自定义输出我的类的一部分。
      • 你不能自定义输出,因为 var_dump 是一个直接输出的 php 函数,你最多可以用 ob_ 函数过滤输出并用一些正则表达式编辑它,但不推荐跨度>
      【解决方案5】:

      如果您正在寻找更具可读性(主观上)的 var_dump,我前段时间写过类似的东西,也许它会对您有用:)

      我想打印每个对象,就好像它是一个数组一样。代码质量不是最好的,但是在我不能用XDebug的时候帮了我。

      class XDump
      {
          private static array $object_hash = []; //workaround for cyclic dependencies
      
          public static function dump($var, bool $withContent = true, ?int $maxDepth = null): void
          {
              $dumpVar = self::convertToArray($var, $withContent, $maxDepth);
              print_r($dumpVar);
              exit();
          }
      
          private static function convertToArray($var, bool $withContent, ?int $maxDepth)
          {
              self::$object_hash = [];
      
              if (!$withContent) {
                  return self::getArrayStructure($var, $maxDepth);
              }
      
              return self::getArray($var, $maxDepth);
          }
      
          private static function getArray($obj, ?int $maxDepth, $mainKey = '', int $depth = 0)
          {
              $simpleReturn = self::getSimpleReturn($obj, $mainKey);
              if (null !== $simpleReturn) {
                  return $simpleReturn;
              }
      
              $result = [];
              $objectArray = (array)$obj;
              foreach ($objectArray as $key => $item) {
                  if (!$maxDepth || $depth <= $maxDepth) {
                      $result[$key] = self::getArray($item, $maxDepth, $key, $depth + 1);
                  }
              }
      
              return self::shortenArray($result);
          }
      
          private static function getArrayStructure($obj, ?int $maxDepth, $mainKey = '', int $depth = 0)
          {
              $simpleReturn = self::getSimpleReturn($obj, $mainKey);
              if (null !== $simpleReturn) {
                  return $simpleReturn;
              }
      
              $result = [];
              $objectArray = (array)$obj;
              foreach ($objectArray as $key => $item) {
                  if (self::hasChildren($item)) {
                      if (!$maxDepth || $depth <= $maxDepth) {
                          $result[$key] = self::getArrayStructure($item, $maxDepth, (string)$key, $depth + 1);
                      }
                  } else {
                      self::throwErrorIfNotPrintable($key, $mainKey);
                      $result['elements'][] = $key;
                  }
              }
              if (isset($result['elements'])) {
                  $elements = implode(' | ', $result['elements']);
                  if (1 === \count($result)) {
                      return $elements;
                  }
      
                  $result['elements'] = $elements;
              }
      
              return self::shortenArray($result);
          }
      
          private static function hasChildren($obj): bool
          {
              return \is_object($obj) || \is_array($obj);
          }
      
          private static function getHashIfAlreadyHashed($obj): ?string
          {
              $hash = self::getObjectHash($obj);
              $existingHash = self::$object_hash[$hash] ?? null;
              self::$object_hash[$hash] = $hash;
      
              return $existingHash;
          }
      
          private static function throwErrorIfNotPrintable($obj, string $name = 'object'): void
          {
              if (!self::isPrintable($obj)) {
                  $type = \gettype($obj);
                  throw new ServerException("Value of {$name} with type {$type} is not handled!");
              }
          }
      
          private static function isPrintable($obj): bool
          {
              return is_scalar($obj) || null === $obj;
          }
      
          private static function getSimpleReturn($obj, $mainKey)
          {
              if (\is_object($obj)) {
                  if (is_subclass_of($obj, \DateTimeInterface::class)) {
                      return TimeHelper::toDateTimeString($obj);
                  }
                  if (\Closure::class === \get_class($obj)) {
                      return 'Closure';
                  }
      
                  $existingHash = self::getHashIfAlreadyHashed($obj);
                  if (null !== $existingHash) {
                      return "Already hashed somewhere else as {$existingHash}!";
                  }
              }
      
              if (\is_string($obj)) {
                  $jsonData = json_decode($obj, true);
                  if ($jsonData) {
                      $jsonData['XDump_IS_JSON_STRING'] = true;
      
                      return $jsonData;
                  }
              }
      
              if (\is_resource($obj)) {
                  $type = get_resource_type($obj);
      
                  return "PHP resource with type: {$type} in {$mainKey}";
              }
      
              if (!self::hasChildren($obj)) {
                  self::throwErrorIfNotPrintable($obj);
      
                  return $obj;
              }
      
              return null;
          }
      
          private static function shortenArray(array $retArray): array
          {
              $shortenRet = [];
              foreach ($retArray as $key => $item) {
                  $shortKey = self::shortenKey((string)$key);
                  $shortenRet[$shortKey] = $item;
              }
      
              return $shortenRet;
          }
      
          private static function shortenKey($key): string
          {
              try {
                  $parts = explode("\0", $key);
                  $shortKey = end($parts);
              } catch (\Throwable $e) {
                  $shortKey = $key;
              }
      
              return $shortKey;
          }
      
          private static function getObjectHash($obj): string
          {
              return \get_class($obj).'|'.spl_object_hash($obj);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-25
        • 2021-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多