bobthecow/psysh

How to deal with monostate pattern?

dereckson opened this issue · 7 comments

According the mysqli_driver class documentation:

The mysqli_driver class is an instance of the monostate pattern, i.e. there is only one driver which can be accessed though an arbitrary amount of mysqli_driver instances.

But here what's happening with psysh:

>>> $driver = new mysqli_driver()
=> mysqli_driver {#2668
     +reconnect: false,
     +report_mode: 0,
   }

>>> $driver->report_mode = MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT;
=> 3

>>> new mysqli_driver
=> mysqli_driver {#2680
     +reconnect: false,
     +report_mode: 0,
   }

At object creation stage, we can see the value for report_mode doesn't respect that monostate pattern.
That can lead to error in diagnostics and debugging.

When we print it, access it, dump it, the object has the correct value:

>>> print_r(new mysqli_driver)
mysqli_driver Object
(
    [client_info] => mysqlnd 8.1.2
    [client_version] => 80102
    [reconnect] => 
    [report_mode] => 3
)

I suspect this behavior is correct for the language: the mysqli_driver source code looks a global struct for the value when we access the report_mode variable.

But it's not optimal to print something other than the real value of the property when we'll query it.

I believe the driver doesn't deal with forking very well. Try disabling it in PsySH (add 'usePcntl' => false to your PsySH config).

Same behavior with usePcntl at false.

The problem seems to be in the dumper, not with PsySH itself:

Screen Shot 2022-02-04 at 11 15 34 PM

Does the var_dump output above match your expectations?

Indeed, every var_dump() call reports the current state of the object.

Thanks! I'll see if I can figure out why VarDumper isn't reporting the current state.

cc @nicolas-grekas in case you have any ideas :)

That's an issue for https://github.com/symfony/symfony indeed. Please send a PR with a failing test case and a fix if you can.

Closing this in favor of symfony/symfony#45487. Thanks @dereckson!