Skip to content

PHP: use __debugInfo in Message to fix endless var_dump #12714

Closed as not planned
@bshaffer

Description

Debugging a Protobuf Message Object

Calling var_dump or print_r on a protobuf message with the Protobuf C extension enabled results very limited, not very useful output:

// Calling var_dump on a Protobuf message (extension enabled):
php > var_dump(new Google\Protobuf\Timestamp());
object(Google\Protobuf\Timestamp)#1 (0) {
}

// Calling print_r on a Protobuf message (extension enabled):
php > var_dump(new Google\Protobuf\Timestamp());
Google\Protobuf\Timestamp Object

When using the Protobuf native library, calls to var_dump and print_r are hard to read and filled with noise:

// Calling var_dump on a Protobuf message (extension disabled):
php > var_dump(new Google\Protobuf\Timestamp());
object(Google\Protobuf\Timestamp)#2 (4) {
  ["desc":"Google\Protobuf\Internal\Message":private]=>
  object(Google\Protobuf\Internal\Descriptor)#424 (13) {
    ["full_name":"Google\Protobuf\Internal\Descriptor":private]=>
    string(25) "google.protobuf.Timestamp"
    ["field":"Google\Protobuf\Internal\Descriptor":private]=>
    array(2) {
      [1]=>
      object(Google\Protobuf\Internal\FieldDescriptor)#428 (14) {
        ["name":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        string(7) "seconds"
        ["json_name":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        string(7) "seconds"
        ["setter":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        string(10) "setSeconds"
        ["getter":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        string(10) "getSeconds"
        ["number":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        int(1)
        ["label":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        int(1)
        ["type":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        int(3)
        ["message_type":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        NULL
        ["enum_type":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        NULL
        ["packed":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        bool(false)
        ["oneof_index":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        int(-1)
        ["proto3_optional":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        bool(false)
        ["containing_oneof":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        NULL
        ["public_desc":"Google\Protobuf\Internal\FieldDescriptor":private]=>
        object(Google\Protobuf\FieldDescriptor)#429 (1) {
          ["internal_desc":"Google\Protobuf\FieldDescriptor":private]=>
          *RECURSION*
        }
      }
// ...

// Calling print_r on a Protobuf message (extension disabled):
php > var_dump(new Google\Protobuf\Timestamp());
Google\Protobuf\Timestamp Object
(
    [desc:Google\Protobuf\Internal\Message:private] => Google\Protobuf\Internal\Descriptor Object
        (
            [full_name:Google\Protobuf\Internal\Descriptor:private] => google.protobuf.Timestamp
            [field:Google\Protobuf\Internal\Descriptor:private] => Array
                (
                    [1] => Google\Protobuf\Internal\FieldDescriptor Object
                        (
                            [name:Google\Protobuf\Internal\FieldDescriptor:private] => seconds
                            [json_name:Google\Protobuf\Internal\FieldDescriptor:private] => seconds
                            [setter:Google\Protobuf\Internal\FieldDescriptor:private] => setSeconds
                            [getter:Google\Protobuf\Internal\FieldDescriptor:private] => getSeconds
                            [number:Google\Protobuf\Internal\FieldDescriptor:private] => 1
                            [label:Google\Protobuf\Internal\FieldDescriptor:private] => 1
                            [type:Google\Protobuf\Internal\FieldDescriptor:private] => 3
                            [message_type:Google\Protobuf\Internal\FieldDescriptor:private] => 
                            [enum_type:Google\Protobuf\Internal\FieldDescriptor:private] => 
                            [packed:Google\Protobuf\Internal\FieldDescriptor:private] => 
                            [oneof_index:Google\Protobuf\Internal\FieldDescriptor:private] => -1
                            [proto3_optional:Google\Protobuf\Internal\FieldDescriptor:private] => 
                            [containing_oneof:Google\Protobuf\Internal\FieldDescriptor:private] => 
                            [public_desc:Google\Protobuf\Internal\FieldDescriptor:private] => Google\Protobuf\FieldDescriptor Object
                                (
                                    [internal_desc:Google\Protobuf\FieldDescriptor:private] => Google\Protobuf\Internal\FieldDescriptor Object
 *RECURSION*
//...

This problem is even worse when debugging instances of RepeatedField, as the result is never-ending.

The fix for this would involve adding support for __debugInfo in the Message class:

    public function __debugInfo()
    {
        return (array) json_decode($this->serializeToJsonString(), true);
    }

For better handling , we can add support for checking specific types (e.g. Google\Protobuf\Timestamp, which returns a string for serializeToJsonString) and adding __debugInfo() for specific classes such as RepeatedField.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

inactiveDenotes the issue/PR has not seen activity in the last 90 days.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions