I wrote a library that can serialize/unserialize PHP object graphs to JSON
data.
Somebody reported it doesn't work on the DateTime class.
Does this deliberately not work?
$date = new DateTime();
var_dump($date);
outputs:
object(DateTime)#1 (3) {
["date"]=>
string(19) "2016-06-04 19:30:19"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
however, this...
$reflection = new ReflectionClass('DateTime');
var_dump($reflection->getProperties());
outputs:
array(0) {
}
The object clearly has properties corresponding to it's internal state, but
reflection doesn't seem to report them?
Also, what comes out of var_dump()
appears to be something intended for
human consumption? I'm guessing that's not the actual internal state of the
object - most likely the internal state consists of the "timezone_type" and
an integer timestamp?
I wrote a library that can serialize/unserialize PHP object graphs to JSON
data.Somebody reported it doesn't work on the DateTime class.
Does this deliberately not work?
$date = new DateTime(); var_dump($date);
outputs:
object(DateTime)#1 (3) { ["date"]=> string(19) "2016-06-04 19:30:19" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" }
however, this...
$reflection = new ReflectionClass('DateTime'); var_dump($reflection->getProperties());
outputs:
array(0) { }
The object clearly has properties corresponding to it's internal state, but
reflection doesn't seem to report them?
I can't tell you why it acts like this, but in case you are looking for
a workaround: https://3v4l.org/V5cfl
Cheers
--
Jordi Boggiano
@seldaek - http://seld.be
I wrote a library that can serialize/unserialize PHP object graphs to JSON
data.Somebody reported it doesn't work on the DateTime class.
Does this deliberately not work?
$date = new DateTime(); var_dump($date);
outputs:
object(DateTime)#1 (3) { ["date"]=> string(19) "2016-06-04 19:30:19" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" }
however, this...
$reflection = new ReflectionClass('DateTime'); var_dump($reflection->getProperties());
outputs:
array(0) { }
The object clearly has properties corresponding to it's internal state,
but
reflection doesn't seem to report them?I can't tell you why it acts like this, but in case you are looking for a
workaround: https://3v4l.org/V5cflCheers
--
Jordi Boggiano
@seldaek - http://seld.be--
The simplified workaround is to cast a DateTime object to an array:
https://3v4l.org/DESiq
On Sat, 04 Jun 2016 22:36:19 +0300, Rasmus Schultz rasmus@mindplay.dk
wrote:
I wrote a library that can serialize/unserialize PHP object graphs to
JSON
data.Somebody reported it doesn't work on the DateTime class.
Does this deliberately not work?
$date = new DateTime(); var_dump($date);
outputs:
object(DateTime)#1 (3) { ["date"]=> string(19) "2016-06-04 19:30:19" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" }
however, this...
$reflection = new ReflectionClass('DateTime'); var_dump($reflection->getProperties());
outputs:
array(0) { }
The object clearly has properties corresponding to it's internal state,
but
reflection doesn't seem to report them?Also, what comes out of
var_dump()
appears to be something intended for
human consumption? I'm guessing that's not the actual internal state of
the
object - most likely the internal state consists of the "timezone_type"
and
an integer timestamp?
Yes, DateTime/DateTimeImmutable classes define custom get_properties
zend_class_entry handler:
http://lxr.php.net/xref/PHP_MASTER/ext/date/php_date.c#2162
Which is called whenever you var_dump()
it or foreach over the object or
call a get_object_vars()
on it: https://3v4l.org/tNJXN
But reflection on the other hand directly uses
zend_class_entry->properties_info
table which DateTime does not have:
http://lxr.php.net/xref/PHP_MASTER/ext/reflection/php_reflection.c#4574
Hi!
The object clearly has properties corresponding to it's internal state, but
reflection doesn't seem to report them?
Reflection reports defined properties, but classes can have dynamic
properties that are not pre-defined. var_dump also has a separate
handler, so the object can present different information to var_dump.
Also, what comes out of
var_dump()
appears to be something intended for
human consumption? I'm guessing that's not the actual internal state of the
object - most likely the internal state consists of the "timezone_type" and
an integer timestamp?
In generic case, you can't have internal state of an object, that's why
it's internal. If you need to serialize data, there are
serialize/unserialize handlers for it.
--
Stas Malyshev
smalyshev@gmail.com
In generic case, you can't have internal state of an object, that's why it's
internal
I know that things like internal state and read-only properties are
possible for classes written in C, but those features aren't possible in
PHP code - classes that behave this way are inconsistent with classes
written in the language, and it becomes a problem in cases such as this.
If you need to serialize data, there are serialize/unserialize handlers
for it.
That is no help at all, when you're implementing a JSON serializer.
You can see the class in question here:
https://github.com/mindplay-dk/jsonfreeze/blob/master/mindplay/jsonfreeze/JsonSerializer.php
Because DateTime does not behave like other classes, the only work-around
is to explicitly handle DateTime with an if/instanceof-statement and handle
that particular class explicitly.
There are plenty of work-arounds - the point is that this class doesn't
behave consistently with any other PHP class.
On Sat, Jun 4, 2016 at 10:23 PM, Stanislav Malyshev smalyshev@gmail.com
wrote:
Hi!
The object clearly has properties corresponding to it's internal state,
but
reflection doesn't seem to report them?Reflection reports defined properties, but classes can have dynamic
properties that are not pre-defined. var_dump also has a separate
handler, so the object can present different information to var_dump.Also, what comes out of
var_dump()
appears to be something intended for
human consumption? I'm guessing that's not the actual internal state of
the
object - most likely the internal state consists of the "timezone_type"
and
an integer timestamp?In generic case, you can't have internal state of an object, that's why
it's internal. If you need to serialize data, there are
serialize/unserialize handlers for it.--
Stas Malyshev
smalyshev@gmail.com
I know that things like internal state and read-only properties are
possible for classes written in C, but those features aren't possible in
PHP code - classes that behave this way are inconsistent with classes
written in the language, and it becomes a problem in cases such as this.That is no help at all, when you're implementing a JSON serializer.
You can see the class in question here:
https://github.com/mindplay-dk/jsonfreeze/blob/master/mindplay/jsonfreeze/JsonSerializer.php
Because DateTime does not behave like other classes, the only work-around
is to explicitly handle DateTime with an if/instanceof-statement and handle
that particular class explicitly.There are plenty of work-arounds - the point is that this class doesn't
behave consistently with any other PHP class.
I have to fully agree with Rasmus here. This is one of those unnecessary
WTF moments for users that forces them to implement work arounds instead
of simply writing good software.
--
Richard "Fleshgrinder" Fussenegger
Hi!
I know that things like internal state and read-only properties are
possible for classes written in C, but those features aren't possible in
PHP code - classes that behave this way are inconsistent with classes
Of course they are possible. See __get/__set. But yes, internal classes
work a bit differently, which is no wonder since they can use internal
handlers which are not available to PHP code.
That is no help at all, when you're implementing a JSON serializer.
Right, DateTime does not implement Serializable. Probably might be a
good idea to make it do that.
Otherwise - though in general it is not a very good idea to serialize
objects which didn't declare they are serializeable, especially internal
ones. But if one feels adventurous the handler to use would be
get_properties, and converting to array uses this handler, so you could
do that. It's the same handler serializers use to get properties, unless
Serializable is implemented or __sleep is defined.
Because DateTime does not behave like other classes, the only
work-around is to explicitly handle DateTime with an
if/instanceof-statement and handle that particular class explicitly.There are plenty of work-arounds - the point is that this class doesn't
behave consistently with any other PHP class.
It does. It's just PHP classes can behave in more ways than you think :)
And to some of the ways there's no good access from PHP space.
Stas Malyshev
smalyshev@gmail.com
Of course they are possible. See __get/__set
Not the same thing at all - PDOStatement::$queryString is a read-only
property, which cannot be overridden, not even with __get() as you would be
able to for regular __get() in a regular PHP class.
It's also impossible to write a PHP class with "internal state" - state
that I can't find at run-time with reflection. That's what makes the
language reflective. Internal state in this sense is something foreign to
PHP as well, the only exception being things like resources, but those
aren't really types in the first place, but handles to file-system objects,
representing state outside of the program.
We're talking about a simple object representing an integer timestamp and a
timezone ID. There is no logical reason those should be hidden - it's just
an implementation detail showing up as an artifact.
It does. It's just PHP classes can behave in more ways than you think :)
And to some of the ways there's no good access from PHP space.
You're describing implementation details - these are features of C, not
features of the PHP language, they happen to leak into the into the PHP
language where they present themselves as inconsistencies.
The fact is that DateTime does not behave like a PHP class in terms of
reflection.
PHP being a reflective language, that's a language inconsistency. What else
would you call it?
On Sun, Jun 5, 2016 at 12:59 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:
Hi!
I know that things like internal state and read-only properties are
possible for classes written in C, but those features aren't possible in
PHP code - classes that behave this way are inconsistent with classesOf course they are possible. See __get/__set. But yes, internal classes
work a bit differently, which is no wonder since they can use internal
handlers which are not available to PHP code.That is no help at all, when you're implementing a JSON serializer.
Right, DateTime does not implement Serializable. Probably might be a
good idea to make it do that.Otherwise - though in general it is not a very good idea to serialize
objects which didn't declare they are serializeable, especially internal
ones. But if one feels adventurous the handler to use would be
get_properties, and converting to array uses this handler, so you could
do that. It's the same handler serializers use to get properties, unless
Serializable is implemented or __sleep is defined.Because DateTime does not behave like other classes, the only
work-around is to explicitly handle DateTime with an
if/instanceof-statement and handle that particular class explicitly.There are plenty of work-arounds - the point is that this class doesn't
behave consistently with any other PHP class.It does. It's just PHP classes can behave in more ways than you think :)
And to some of the ways there's no good access from PHP space.Stas Malyshev
smalyshev@gmail.com
Hi!
It's also impossible to write a PHP class with "internal state" - state
that I can't find at run-time with reflection. That's what makes the
language reflective. Internal state in this sense is something foreign
to PHP as well, the only exception being things like resources, but
those aren't really types in the first place, but handles to file-system
objects, representing state outside of the program.
It's not foreign to PHP, it's unavailable to userspace, yes. Internal
functions have access to more capabilities than userspace ones, it has
always been the case in PHP.
We're talking about a simple object representing an integer timestamp
and a timezone ID. There is no logical reason those should be hidden -
it's just an implementation detail showing up as an artifact.
There is a reason, or rather reasons, one of them is that internal
representation of the data and user-visible one are different. What is
inside the object is not what you see on the outside.
You're describing implementation details - these are features of C, not
features of the PHP language, they happen to leak into the into the PHP
language where they present themselves as inconsistencies.
You can call it whatever name you like, I'm just explaining how it
actually works :) Calling everything you don't understand
"inconsistencies" seems to be new fashion, but the fact is internal API
has more capabilities than user-space API in PHP. It is a deliberate and
very old decision stemming from the fact that it is very hard -
impossible, really - to give user-space access to engine features safely
to PHP code. OTOH, some interesting things only possible if you have
access to these features.
The fact is that DateTime does not behave like a PHP class in terms of
reflection.
It behaves like internal PHP class. You can't really expose state of
internal classes via reflection, since in general case this state does
not have proper representation in PHP terms besides that very class itself.
Stas Malyshev
smalyshev@gmail.com
In generic case, you can't have internal state of an object, that's why
it's internal. If you need to serialize data, there are
serialize/unserialize handlers for it.
This is also why DateTime is useless for many data handling functions
since having to work with 'long hand' for something which is essentially
a simple integer value is a heavy overhead. We are stuck with using
Timezone management since there is nothing reasonably
reliable as an alternative, but we only need timezone to DISPLAY the
right text, not manage the raw dates.
An alternate date/time variable is essential anyway, which is why some
of these discussions are so utterly pointless anyway. date and time are
as essential to any system as integer and float but all anybody seems to
be bothered about is the same limited subset of 'types' ?
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk