11

是否可以覆盖自定义类的 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
  }
}

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

谢谢。

4

5 回答 5

15

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 上遇到错误,因为返回 a string

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

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

于 2014-09-20T04:01:10.847 回答
1

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

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

于 2013-05-17T13:35:08.747 回答
0

您不能覆盖核心 PHP 函数。

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

class myClass {
    public function __toString(){
        // custom var_dump() content here then output it
    }
}

$myClass = new myClass();

echo $myClass;
于 2013-05-17T13:35:23.047 回答
0

没有意义覆盖 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;

例子在这里

于 2013-05-17T13:49:29.163 回答
0

如果您正在寻找更具可读性(主观上)的 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);
    }
}
于 2021-11-10T11:28:11.777 回答