ID: 38935
User updated by: marcus at synchromedia dot co dot uk
Reported By: marcus at synchromedia dot co dot uk
-Status: Bogus
+Status: Closed
-Bug Type: Class/Object related
+Bug Type: Documentation problem
Operating System: All
PHP Version: 5.1.6
New Comment:
It turns out that this was actually a documentation problem,
and apparently a fix has been posted in docs. So, the
'strange' entries are intentional, and the new docs will
explain them.
Previous Comments:
------------------------------------------------------------------------
[2006-09-23 18:27:20] marcus at synchromedia dot co dot uk
Well, that's good to know, but it does mean that you're
justifying undocumented behaviour with yet more undocumented
behaviour.
I see that these null bytes are there, but they're not
separators; they're prefixes to both class and property
name, that is, the resulting array keys are of the form:
NULL<classname>NULL<propertyname>
I still fail to see how this is bogus when it's so wildly
different to what's documented, and is implemented in such a
way as to be useful in only the most obtuse of situations,
to the detriment of all other occasions. One change that
would make all this much more palatable while preserving the
additional information AND conforming closer to the docs:
only provide extended class information for properties that
are NOT in the current class. For example:
<?php
class A {
private $A;
}
class B extends A {
private $A;
public $B;
}
$a = (array)new B;
foreach($a as $k => $v) {
echo bin2hex($k)."\n";
}
?>
At present this produces:
00420041
00410041
My suggestion is to change that to:
00420041
41
That way we will be in the situation that all unambiguous
properties in the current class are available using their
unmodified names, just like the docs say. The only remaining
issue is with protected values - I don't know that
preserving that status is of much value anyway - it's not as
if you can cast back from an array to an object anyway.
------------------------------------------------------------------------
[2006-09-23 17:34:44] [EMAIL PROTECTED]
There are separators, null bytes.
------------------------------------------------------------------------
[2006-09-23 16:39:22] marcus at synchromedia dot co dot uk
I'm sorry but that's a bogus explanation. "Please double-
check the documentation"? What you describe is contrary to
the documentation.
The reasoning you express also fails completely on my point
about there being no separator between class name and
property name. How can you consider this to be reasonable
behaviour?:
class A {
private $A;
}
class B extends A {
private $A;
public $AA;
}
var_dump((array)new B());
array(3) {
["BA"]=>
NULL
["AA"]=>
NULL
["AA"]=>
NULL
}
Given that this undocumented behaviour is thus proven
ambiguous, unreliable and contrary to existing docs, how can
you say that it's 'needed'? Are you saying that there's
widespread code that depends on this weirdness, when 99% of
use cases will not expect it?
At the very least this is a valid documentation bug.
------------------------------------------------------------------------
[2006-09-23 16:09:53] [EMAIL PROTECTED]
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php
The class information is needed, see for example
class A {
private $p;
}
class B extends A {
private $p;
}
var_dump((array)new B());
------------------------------------------------------------------------
[2006-09-23 15:31:13] marcus at synchromedia dot co dot uk
Description:
------------
When you cast an object to an array, and the object contains
private or protected members, the resulting array keys are
effectively corrupted.
Private members get the object class prepended to their
name. Protected members get a '*' prepended to their name.
The docs say:
"If you convert an object to an array, you get the
properties (member variables) of that object as the array's
elements. The keys are the member variable names."
In reality, this is not true.
I don't see any real value in preserving access levels -
arrays are not objects and they should not try to behave as
them. You can find out the access level via introspection if
you really need it, and by definition you have an instance
handy to look at.
If it's intentional, it's not very helpful. As there's no
separator between class name and variable name it's
impossible to separate it correctly - if I had a property
called 'Myclassfield1' in a Myclass instance, I would not be
able to tell if it was a public property called
'Myclassfield1' or a private property called 'field1'.
As this is deviating from documented behaviour and it's also
fairly useless as it stands, I don't see any reason for
keeping it like this.
Reproduce code:
---------------
<?php
class Myclass {
public $field1 = '';
private $field2 = '';
protected $field3 = '';
}
$myclass = new Myclass;
var_dump($myclass);
var_dump((array)$myclass);
?>
Expected result:
----------------
object(Myclass)#1 (3) {
["field1"]=>
string(0) ""
["field2:private"]=>
string(0) ""
["field3:protected"]=>
string(0) ""
}
array(3) {
["field1"]=>
string(0) ""
["field2"]=>
string(0) ""
["field3"]=>
string(0) ""
}
Actual result:
--------------
object(Myclass)#1 (3) {
["field1"]=>
string(0) ""
["field2:private"]=>
string(0) ""
["field3:protected"]=>
string(0) ""
}
array(3) {
["field1"]=>
string(0) ""
["Myclassfield2"]=>
string(0) ""
["*field3"]=>
string(0) ""
}
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=38935&edit=1