Hello Everyon,
Casting a SimpleXML object to an array gives different results in PHP
5.2.5 and PHP 5.3-dev.
Source:
$xml = simplexml_load_file("sample.xml");
foreach($xml->column as $column) {
var_dump($column);
var_dump((array)$column);
}
sample.xml
?xml version="1.0"?>
<cpdata>
<column name="ENTERTAINMENT">
<module>cv</module>
<module>entsimp</module>
</column>
<column name="SEAT CONTROL">
<module>pp</module>
<module>sc</module>
</column>
</cpdata>
PHP 5.2 output:
object(SimpleXMLElement)#4 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
array(2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
object(SimpleXMLElement)#5 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}
array(2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}
PHP 5.3 output:
object(SimpleXMLElement)#4 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
array(1) {
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
object(SimpleXMLElement)#5 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}
array(1) {
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}
Not that the attributes are gone when SimpleXML objects are converted in
PHP 5.3. Is this a bug or a feature change?
- Frank
Hi Frank,
please open a bugreport about this issue. This would start the internal
process of verifying this.
-- Marco
Hello Everyon,
Casting a SimpleXML object to an array gives different results in PHP
5.2.5 and PHP 5.3-dev.Source:
$xml = simplexml_load_file("sample.xml");
foreach($xml->column as $column) {
var_dump($column);
var_dump((array)$column);
}sample.xml
?xml version="1.0"?>
<cpdata>
<column name="ENTERTAINMENT">
<module>cv</module>
<module>entsimp</module>
</column>
<column name="SEAT CONTROL">
<module>pp</module>
<module>sc</module>
</column>
</cpdata>PHP 5.2 output:
object(SimpleXMLElement)#4 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
array(2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
object(SimpleXMLElement)#5 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}
array(2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}PHP 5.3 output:
object(SimpleXMLElement)#4 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
array(1) {
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
object(SimpleXMLElement)#5 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}
array(1) {
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}Not that the attributes are gone when SimpleXML objects are converted in
PHP 5.3. Is this a bug or a feature change?
- Frank
--
--
Marco Kaiser
Hi Frank,
Frank M. Kromann wrote:
Hello Everyon,
Casting a SimpleXML object to an array gives different results in PHP
5.2.5 and PHP 5.3-dev.
This is due to the implementation of the get_debug_info handler merged
from HEAD.
The same result happens when calling get_object_vars on a
SimpleXMLElement object.
Marcus, was it intended to only include @attributes with print_r/var_dump?
Rob
Source:
$xml = simplexml_load_file("sample.xml");
foreach($xml->column as $column) {
var_dump($column);
var_dump((array)$column);
}sample.xml
?xml version="1.0"?>
<cpdata>
<column name="ENTERTAINMENT">
<module>cv</module>
<module>entsimp</module>
</column>
<column name="SEAT CONTROL">
<module>pp</module>
<module>sc</module>
</column>
</cpdata>PHP 5.2 output:
object(SimpleXMLElement)#4 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
array(2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
object(SimpleXMLElement)#5 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}
array(2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}PHP 5.3 output:
object(SimpleXMLElement)#4 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
array(1) {
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
object(SimpleXMLElement)#5 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}
array(1) {
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}Not that the attributes are gone when SimpleXML objects are converted in
PHP 5.3. Is this a bug or a feature change?
- Frank
This happens with many more functions. So i can verify this bug.
php -r "echo md5(serialize(simplexml_load_file('example.xml'))) . PHP_EOL
.
phpversion()
. PHP_EOL;"
Output PHP 5.2.5:
a6d7776fcb0e9c085b0d5972df792dac
5.2.5
Output PHP 5.3.0-dev (latest snap)
3e442cb7c8507c8941011735bb46e6de
5.3.0-dev
-- Marco
Hi Frank,
Frank M. Kromann wrote:
Hello Everyon,
Casting a SimpleXML object to an array gives different results in PHP
5.2.5 and PHP 5.3-dev.This is due to the implementation of the get_debug_info handler merged
from HEAD.
The same result happens when calling get_object_vars on a
SimpleXMLElement object.Marcus, was it intended to only include @attributes with print_r/var_dump?
Rob
Source:
$xml = simplexml_load_file("sample.xml");
foreach($xml->column as $column) {
var_dump($column);
var_dump((array)$column);
}sample.xml
?xml version="1.0"?>
<cpdata>
<column name="ENTERTAINMENT">
<module>cv</module>
<module>entsimp</module>
</column>
<column name="SEAT CONTROL">
<module>pp</module>
<module>sc</module>
</column>
</cpdata>PHP 5.2 output:
object(SimpleXMLElement)#4 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
array(2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
object(SimpleXMLElement)#5 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}
array(2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}PHP 5.3 output:
object(SimpleXMLElement)#4 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
array(1) {
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
object(SimpleXMLElement)#5 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}
array(1) {
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}Not that the attributes are gone when SimpleXML objects are converted in
PHP 5.3. Is this a bug or a feature change?
- Frank
--
--
Marco Kaiser
Hello Rob,
this is intended. The 5.2 solution is just a hack and returns a wrong
result in the first place. The hack was however introduced to make
development easier. Now with 5.3 we were able to change the API and coudl
apply the solution that was first developed in HEAD.
marcus
Sunday, December 9, 2007, 1:22:09 PM, you wrote:
Hi Frank,
Frank M. Kromann wrote:
Hello Everyon,
Casting a SimpleXML object to an array gives different results in PHP
5.2.5 and PHP 5.3-dev.This is due to the implementation of the get_debug_info handler merged
from HEAD.
The same result happens when calling get_object_vars on a
SimpleXMLElement object.
Marcus, was it intended to only include @attributes with print_r/var_dump?
Rob
Source:
$xml = simplexml_load_file("sample.xml");
foreach($xml->column as $column) {
var_dump($column);
var_dump((array)$column);
}sample.xml
?xml version="1.0"?>
<cpdata>
<column name="ENTERTAINMENT">
<module>cv</module>
<module>entsimp</module>
</column>
<column name="SEAT CONTROL">
<module>pp</module>
<module>sc</module>
</column>
</cpdata>PHP 5.2 output:
object(SimpleXMLElement)#4 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
array(2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
object(SimpleXMLElement)#5 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}
array(2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}PHP 5.3 output:
object(SimpleXMLElement)#4 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(13) "ENTERTAINMENT"
}
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
array(1) {
["module"]=>
array(2) {
[0]=>
string(2) "cv"
[1]=>
string(7) "entsimp"
}
}
object(SimpleXMLElement)#5 (2) {
["@attributes"]=>
array(1) {
["name"]=>
string(12) "SEAT CONTROL"
}
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}
array(1) {
["module"]=>
array(2) {
[0]=>
string(2) "pp"
[1]=>
string(2) "sc"
}
}Not that the attributes are gone when SimpleXML objects are converted in
PHP 5.3. Is this a bug or a feature change?
- Frank
Best regards,
Marcus
Ok, it's supposed to be this way right? If i define a custom class in
the global namespace called "myClass" and I'm in another namespace, I
can only access it using ::myClass, not just myClass (without the
colons)? Seems to me that it should check the local namespace and then
the global, but it only checks the globl if i specifically tell it to
with the preceding "::".
-----Ursprüngliche Nachricht-----
Von: Sam Barrow [mailto:sam@sambarrow.com]
Gesendet: Montag, 10. Dezember 2007 22:48
An: internals@lists.php.net
Betreff: [PHP-DEV] Namespace resolutionOk, it's supposed to be this way right? If i define a custom class in
the global namespace called "myClass" and I'm in another namespace, I
can only access it using ::myClass, not just myClass (without the
colons)? Seems to me that it should check the local namespace and then
the global, but it only checks the globl if i specifically tell it to
with the preceding "::".
From http://www.php.net/manual/en/language.namespaces.rules.php:
--
Inside namespace (say A::B), calls to unqualified class names are resolved at run-time. Here is how a call to new C() is resolved:
- It looks for a class from the current namespace : A::B::C().
- It tries to find and call the internal class C().
- It attemts to autoload A::B::C(). C().
To reference a user defined class in the global namespace, new ::C() has to be used.
Which is exactly what you observed.
-mp.
The problem I see with that is that if I have an application that uses
a 3rd-party library which does not use namespaces, I need to
use ::LibClass everywhere. Until they switch to namespaces - then I
need to touch hundreds and thousands lines of code. If LibClass were
looked up in the global namespace, too, I could simply add the
appropriate import statements at the top of each file.
Anyways, the process you described seems flawed in another fashion: It
looks up a class in the namespace first, then an internal php class,
then it tries an autoload. That does not make sense. Lets say I run
some code as you described, and there is a class C(), but it's not
been autoloaded yet. The internal class C is used. Then, later, the
autoloading of A::B::C() is somehow forced. Now, if the same code runs
again, a different class is used. That sounds like nonsense.
David
Am 11.12.2007 um 08:31 schrieb Matthias Pigulla:
-----Ursprüngliche Nachricht-----
Von: Sam Barrow [mailto:sam@sambarrow.com]
Gesendet: Montag, 10. Dezember 2007 22:48
An: internals@lists.php.net
Betreff: [PHP-DEV] Namespace resolutionOk, it's supposed to be this way right? If i define a custom class in
the global namespace called "myClass" and I'm in another namespace, I
can only access it using ::myClass, not just myClass (without the
colons)? Seems to me that it should check the local namespace and
then
the global, but it only checks the globl if i specifically tell it to
with the preceding "::".From http://www.php.net/manual/en/language.namespaces.rules.php:
--
Inside namespace (say A::B), calls to unqualified class names are
resolved at run-time. Here is how a call to new C() is resolved:
- It looks for a class from the current namespace : A::B::C().
- It tries to find and call the internal class C().
- It attemts to autoload A::B::C(). C().
To reference a user defined class in the global namespace, new ::C()
has to be used.Which is exactly what you observed.
-mp.
Calm down David :) He is referring only 3 cases. Please check the link he is
providing too :)
Von: David Zülke [mailto:dz@bitxtender.com]
The problem I see with that is that if I have an application that uses
a 3rd-party library which does not use namespaces, I need to
use ::LibClass everywhere. Until they switch to namespaces - then I
need to touch hundreds and thousands lines of code. If LibClass were
looked up in the global namespace, too, I could simply add the
appropriate import statements at the top of each file.
You got a point.
Anyways, the process you described seems flawed in another fashion: It
looks up a class in the namespace first, then an internal php class,
then it tries an autoload. That does not make sense. Lets say I run
some code as you described, and there is a class C(), but it's not
been autoloaded yet. The internal class C is used. Then, later, the
autoloading of A::B::C() is somehow forced. Now, if the same code runs
again, a different class is used. That sounds like nonsense.
Exactly what Chuck and Greg tried to point out, providing examples for what you describe.
internals@lists.php.net/msg31217.html" rel="nofollow" target="_blank">http://www.mail-archive.com/internals@lists.php.net/msg31217.html
In my opinion one of the biggest weak points. In order to make things work consistently and reliable (behaviour does not change because of the order in which files are included or because new core classes are added), you need to 1) make sure all the stuff you use is already known (that is, refrain from using __autoload and revert to require() at the top of your files) or 2) explicitly use/import all your classes, even the ones from your namespace inside your namespace.
That is because __autoload comes after internal classes (which comes after already known classes from the current NS) for unqualified names. Approach 1) makes the names "already known", 2) turns the unqualified names into qualified ones by means of aliasing.
:(
-mp.
The problem I see with that is that if I have an application that uses a
3rd-party library which does not use namespaces, I need to use
::LibClass everywhere. Until they switch to namespaces - then I need to
touch hundreds and thousands lines of code. If LibClass were looked up
in the global namespace, too, I could simply add the appropriate import
statements at the top of each file.
But also it means that namespaced library would be influenced by any use
code around, which was exactly the thing we tried to avoid.
Anyways, the process you described seems flawed in another fashion: It
looks up a class in the namespace first, then an internal php class,
then it tries an autoload. That does not make sense. Lets say I run some
Actually, it does :)
code as you described, and there is a class C(), but it's not been
autoloaded yet. The internal class C is used. Then, later, the
autoloading of A::B::C() is somehow forced. Now, if the same code runs
again, a different class is used. That sounds like nonsense.
Not, it's not nonsense - try to find other way that allows overriding
internal class names and doesn't force exhaustive autoload search on
each access to internal class - and you'll understand why it makes sense.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Am 11.12.2007 um 19:00 schrieb Stanislav Malyshev:
The problem I see with that is that if I have an application that
uses a 3rd-party library which does not use namespaces, I need to
use ::LibClass everywhere. Until they switch to namespaces - then I
need to touch hundreds and thousands lines of code. If LibClass
were looked up in the global namespace, too, I could simply add the
appropriate import statements at the top of each file.But also it means that namespaced library would be influenced by any
use code around, which was exactly the thing we tried to avoid.Anyways, the process you described seems flawed in another fashion:
It looks up a class in the namespace first, then an internal php
class, then it tries an autoload. That does not make sense. Lets
say I run someActually, it does :)
code as you described, and there is a class C(), but it's not been
autoloaded yet. The internal class C is used. Then, later, the
autoloading of A::B::C() is somehow forced. Now, if the same code
runs again, a different class is used. That sounds like nonsense.Not, it's not nonsense - try to find other way that allows
overriding internal class names and doesn't force exhaustive
autoload search on each access to internal class - and you'll
understand why it makes sense.
Ah. Yes, that makes perfect sense to me. The logical solution must be
then, however, not to implement namespaces at all, or requiring code
that is either namespaced or has imported a namespace to do sth like
"use php;", as others suggested last week. I understand the reason
for the behavior from an implementational standpoint, but I think it
really is obvious that such a namespace solution would be completely
useless, as it would not be possible under any circumstances to
provide code that works in a reliable fashion.
Or, as an alternative, introduce an optional third argument to
spl_autoload_register where people can give a namespace name for which
the autoloading should be performed. That would cut down overhead
since just the autoload functions of currently imported namespaces
would have to be called.
I don't really think, though, that doing something like use php;
is a tall order, is it? It would only be necessary for those that
consume namespaces in their code via "use" statements, hence no BC
break.
- David
Ah. Yes, that makes perfect sense to me. The logical solution must be
then, however, not to implement namespaces at all, or requiring code
It's not a solution, it's refusing to solve a problem.
for the behavior from an implementational standpoint, but I think it
really is obvious that such a namespace solution would be completely
useless, as it would not be possible under any circumstances to provide
If it's "obvious" for you that namespaces are useless, probably you need
to give your obviousness-meter a check-up. They were found useful by
many people, even if there are things to work out here and there - which
happens with each new concept not tested in the field.
Or, as an alternative, introduce an optional third argument to
spl_autoload_register where people can give a namespace name for which
the autoloading should be performed. That would cut down overhead since
There's no such thing as "namespace name for which autoloding is
performed". Autoloader receives a full class name, that's it. How this
name was created is irrelevant.
just the autoload functions of currently imported namespaces would have
to be called.
I don't understand what do you mean here, but it doesn't matter, since
autoload call on each class access is very bad regardless of how it's
implemented internally.
I don't really think, though, that doing something like use php; is
a tall order, is it? It would only be necessary for those that consume
"use whatever;" is a no-op. There's even warning about it in the engine.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Am 11.12.2007 um 21:22 schrieb Stanislav Malyshev:
Ah. Yes, that makes perfect sense to me. The logical solution must
be then, however, not to implement namespaces at all, or requiring
codeIt's not a solution, it's refusing to solve a problem.
Well, if your answer is that it makes sense this way and that it's not
gonna be changed because it cannot be implemented without significant
overhead, then I need to say that it would be better to have no
namespaces rather than significantly flawed namespaces.
for the behavior from an implementational standpoint, but I think
it really is obvious that such a namespace solution would be
completely useless, as it would not be possible under any
circumstances to provideIf it's "obvious" for you that namespaces are useless, probably you
need to give your obviousness-meter a check-up. They were found
useful by many people, even if there are things to work out here and
there - which happens with each new concept not tested in the field.
They are not useless. They would just be useless
Or, as an alternative, introduce an optional third argument to
spl_autoload_register where people can give a namespace name for
which the autoloading should be performed. That would cut down
overhead sinceThere's no such thing as "namespace name for which autoloding is
performed". Autoloader receives a full class name, that's it. How
this name was created is irrelevant.just the autoload functions of currently imported namespaces would
have to be called.I don't understand what do you mean here, but it doesn't matter,
since autoload call on each class access is very bad regardless of
how it's implemented internally.
Yes, because you didn't bother to even read what I wrote. I'll explain
it with an example for you, maybe that helps:
Let's assume we have ten autoloaders. We are, by import, in namespace
Name::Space. Someone does new DateTime();
You would now have to go through all ten autoloaders before you can
decide that no userspace class DateTime exists in any namespace, and
thus the PHP internal class DateTime may be used.
However, if it were possible to do this:
spl_autoload_register(array('Name::Space::Ship', 'autoload'),
'Name::Space');
Then you could would not have to call ten autoloaders, but just those
registered for the currently imported namespaces. As we've only
imported "Name::Space", this is just the one I showed above. Class not
found? Okay, use PHP's DateTime. Overhead gone.
I don't really think, though, that doing something like use
php; is a tall order, is it? It would only be necessary for
those that consume"use whatever;" is a no-op. There's even warning about it in the
engine.
Stas, really, stop retreating to technical details and making me look
like a fool when you're tired of coming up with arguments. You very
well know I meant "import". Reply to the suggestion in a respectful
manner, or give it a miss.
David
You would now have to go through all ten autoloaders before you can
decide that no userspace class DateTime exists in any namespace, and
thus the PHP internal class DateTime may be used.
Even one autoloader is bad enough to not even have to consider the case
of ten autoloaders. Remember, autoloader is filesystem access.
Filesystem access on each class mention is a disaster.
like a fool when you're tired of coming up with arguments. You very well
know I meant "import". Reply to the suggestion in a respectful manner,
or give it a miss.
I'm afraid I still do not understand what did you mean. Could you
explain in more detail?
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Stanislav Malyshev wrote:
You would now have to go through all ten autoloaders before you can
decide that no userspace class DateTime exists in any namespace, and
thus the PHP internal class DateTime may be used.Even one autoloader is bad enough to not even have to consider the case
of ten autoloaders. Remember, autoloader is filesystem access.
Filesystem access on each class mention is a disaster.
it's just slow. regardless namespaces need to work in conjunction with
autoload in a perdictable and understandable manner ... I get the distinct
impression that namespaces+autoload is going to introduce a serious wtf factor.
given that autoload is 'out there' and the raison d'etre of namespaces is,
amongst other things, to enable better leveraging of third party code namespaces
must concede to autoload if only for the reason that one is garanteed to have to
deal with both together at some point if one is ever to seriously make use of
third party namespaced code.
as an aside, is autoload becoming the new 'magic_quotes'?
like a fool when you're tired of coming up with arguments. You very
well know I meant "import". Reply to the suggestion in a respectful
manner, or give it a miss.I'm afraid I still do not understand what did you mean. Could you
explain in more detail?
Am 11.12.2007 um 22:31 schrieb Stanislav Malyshev:
You would now have to go through all ten autoloaders before you can
decide that no userspace class DateTime exists in any namespace,
and thus the PHP internal class DateTime may be used.Even one autoloader is bad enough to not even have to consider the
case of ten autoloaders. Remember, autoloader is filesystem access.
Filesystem access on each class mention is a disaster.like a fool when you're tired of coming up with arguments. You very
well know I meant "import". Reply to the suggestion in a respectful
manner, or give it a miss.I'm afraid I still do not understand what did you mean. Could you
explain in more detail?
Sure. My basic idea was that since the issue we're talking about can
only occur either in namespaced code, or in code that uses namespaced
components, there would not be any backwards compatibility problem
with something like:
import Name::Space;
// only stuff from Name::Space available, no PHP internal stuff
import php;
// now PHP's classes are loaded, too.
$d = new DateTime(); // this loads php's DateTime, since the first
existance check gives that one, so no autoloading is ever performed,
even if there is a Name::Space::DateTime class.
Now, assuming that someone wants to use PHP stuff and Name::Space
stuff of the same name, they can do import php as php; (or
import Name::Space as NS and then new NS::DateTime()) for either
statement to work around that. In any case, it would never introduce
issues. My statement 'doing a "use php" is not a tall
order' (which means it's not asking much from the developer to do
that) from one of the previous mails was referring to just that. Think
of other languages with namespace/package concepts. If you want to use
java's date/time features, you need to do some kind of import
java.util.blah stuff, too. I don't think that PHP's internal stuff
needs to be magically available. We can force developers to explicitly
request access to it.
Did that explanation help? :)
David
import Name::Space;
// only stuff from Name::Space available, no PHP internal stuff
import php;
// now PHP's classes are loaded, too.
So "import php" make internal classes always take priority even when
there's a class in this namespace by that name? But you could achiever
the same just by avoiding naming classes the same as internal classes,
you surely know which classes are in your own namespace? Since in both
cases code change is needed, why that one is better? If you created
Name::Space::DateTime, surely there was some intent in having it named
specifically the same as DateTime class in PHP?
issues. My statement 'doing a "use php" is not a tall order' (which
means it's not asking much from the developer to do that) from one of
Not using names of classes same as internal classes is not a big deal
either - all PHP programmers do it right now :) I just don't see any
added value in inventing artificial syntax constructs which don't do
what they implied meaning is (they don't import anything) but instead
change engine rules.
the previous mails was referring to just that. Think of other languages
with namespace/package concepts. If you want to use java's date/time
features, you need to do some kind of import java.util.blah stuff, too.
Java package system is very different. For starters, they don't have
global space at all. And they have offline compilation stage which
verifies all the dependencies.
I don't think that PHP's internal stuff needs to be magically available.
We can force developers to explicitly request access to it.
We can, but we should not. Internal classes are internal for a reason -
people use them a lot. Making it hard to access frequently used classes
to enable rarely used functionality is not the right way to go.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Am 11.12.2007 um 23:36 schrieb Stanislav Malyshev:
import Name::Space;
// only stuff from Name::Space available, no PHP internal stuff
import php;
// now PHP's classes are loaded, too.So "import php" make internal classes always take priority even when
there's a class in this namespace by that name? But you could
achiever the same just by avoiding naming classes the same as
internal classes, you surely know which classes are in your own
namespace? Since in both cases code change is needed, why that one
is better? If you created Name::Space::DateTime, surely there was
some intent in having it named specifically the same as DateTime
class in PHP?
Ah. Now that you mention it, there was a flaw in my logic. The idea
was not that PHP classes take precedence, but in this case, PHP's
DateTime class would already be "loaded" so no autoload would be
attempted for a Name::Space::DateTime. If, however, that
Name::Space::DateTime was already autoloaded by the time we reach that
code, things would just break. Hmmh. Jochem pointed it out in the
other message; I think this autoloading thing is going to be tricky...
Java package system is very different. For starters, they don't have
global space at all. And they have offline compilation stage which
verifies all the dependencies.
Yes, sure. I was just saying that other languages also require you to
import language-internal stuff from time to time.
I don't think that PHP's internal stuff needs to be magically
available. We can force developers to explicitly request access to
it.We can, but we should not. Internal classes are internal for a
reason - people use them a lot. Making it hard to access frequently
used classes to enable rarely used functionality is not the right
way to go.
Okay, but what do we do about the issue described initially then?
Here's a concrete example to show the problem:
<Name/Space/DateTime.php>
namespace Name::Space;
class DateTime {}
<Name/Space/Ship.php>
namespace Name::Space;
class Ship {
public static function __autoload($className) {
// ... autoloader, can load Name::Space::DateTime
}
}
<somestuff.php>
function someStuffWeDoNotHaveControlOver() {
$foo = new Name::Space::DateTime();
// ...
}
<setup.php>
require_once('Name/Space/Ship.php');
spl_autoload_register(array('Name::Space::Ship', '__autoload'));
<example.php>
require_once('setup.php');
import Name::Space;
$d = new DateTime(); // a PHP DateTime
someStuffWeDoNotHaveControlOver();
$d = new DateTime(); // a Name::Space::DateTime now!
See what I mean?
David
<example.php>
require_once('setup.php');
import Name::Space;
$d = new DateTime(); // a PHP DateTime
someStuffWeDoNotHaveControlOver();
$d = new DateTime(); // a Name::Space::DateTime now!
Of course not. DateTime would be just DateTime there, not
Name::Space::DateTime, since you are not inside namespace Name::Space
but in global context.
--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Am 12.12.2007 um 00:27 schrieb Stanislav Malyshev:
<example.php>
require_once('setup.php');
import Name::Space;
$d = new DateTime(); // a PHP DateTime
someStuffWeDoNotHaveControlOver();
$d = new DateTime(); // a Name::Space::DateTime now!Of course not. DateTime would be just DateTime there, not
Name::Space::DateTime, since you are not inside namespace
Name::Space but in global context.
Why? I did import Name::Space. According to the current lookup rules,
the first new DateTime() call creates a PHP internal class since
Name::Space::DateTime cannot be found (and autoloading would only be
triggered later), and the second DateTime() call does create
Name::Space::DateTime because by then, it has been autoloaded and thus
can be found in the current namespace.
David
Why? I did import Name::Space. According to the current lookup rules,
the first new DateTime() call creates a PHP internal class since
Name::Space::DateTime cannot be found (and autoloading would only be
triggered later), and the second DateTime() call does create
Name::Space::DateTime because by then, it has been autoloaded and thus
can be found in the current namespace.
Current namespace in your example is global space. Please reread the
docs on what "use" operator does and what "namespace" operator does. I
would also recommend avoiding "import" in your examples sine such
operator no longer exists.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Am 12.12.2007 um 01:04 schrieb Stanislav Malyshev:
Why? I did import Name::Space. According to the current lookup
rules, the first new DateTime() call creates a PHP internal class
since Name::Space::DateTime cannot be found (and autoloading would
only be triggered later), and the second DateTime() call does
create Name::Space::DateTime because by then, it has been
autoloaded and thus can be found in the current namespace.Current namespace in your example is global space. Please reread the
docs on what "use" operator does and what "namespace" operator does.
I would also recommend avoiding "import" in your examples sine such
operator no longer exists.
Ah, yes, of course, my bad. Well, the problem still exists inside a
namespace, right?
And didn't you say "use" is a NOP just two hours ago?
David
And didn't you say "use" is a NOP just two hours ago?
No, I didn't. I said "use whatever;" - where "whatever" is one-term name
- is a NOP.
--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Von: Stanislav Malyshev [mailto:stas@zend.com]
But you could achiever
the same just by avoiding naming classes the same as internal classes,
you surely know which classes are in your own namespace?
...
Not using names of classes same as internal classes is not a big deal
either - all PHP programmers do it right now :)
Rumor exists that sometimes new internal classes show up in late RCs. And as you try to name your classes so that the name describes the modeled construct best, it is not surprising that core wants to name such a new class "Date" just as userland folks had their classes named "Date" as well before (shame on them).
I always thought that one of the prime reasons for providing namespaces was to mitigate this risk of breakage in a simple, predictable and user-friendly manner.
-mp.
Matthias Pigulla wrote:
Von: Stanislav Malyshev [mailto:stas@zend.com]
But you could achiever the same just by avoiding naming classes the
same as internal classes, you surely know which classes are in your
own namespace?
...
Not using names of classes same as internal classes is not a big
deal either - all PHP programmers do it right now :)Rumor exists that sometimes new internal classes show up in late RCs.
And as you try to name your classes so that the name describes the
modeled construct best, it is not surprising that core wants to name
such a new class "Date" just as userland folks had their classes
named "Date" as well before (shame on them).I always thought that one of the prime reasons for providing
namespaces was to mitigate this risk of breakage in a simple,
predictable and user-friendly manner.
Hi,
I brought this issue up in the original thread about namespace
implementation. I've also brought it up since then twice, including in
the long rebuttal to Derick's RFC. Here again is the obvious solution:
<?php
namespace Foo;
use Foo::DateTime;
$a = new DateTime;
?>
now __autoload() is called. End of crisis. Also possible is:
<?php
namespace Foo::Long::Thing;
use Foo::Long::Thing as me;
$a = new me::DateTime;
?>
for a namespace with many classes.
Could we move on from this problem? It is easily solved with the
current implementation.
Greg
Am 11.12.2007 um 22:31 schrieb Stanislav Malyshev:
You would now have to go through all ten autoloaders before you can
decide that no userspace class DateTime exists in any namespace,
and thus the PHP internal class DateTime may be used.Even one autoloader is bad enough to not even have to consider the
case of ten autoloaders. Remember, autoloader is filesystem access.
Filesystem access on each class mention is a disaster.
A simple
if(strpos($className 'My::Namespace::') === 0)
will fix that just fine.
- David
A simple
if(strpos($className 'My::Namespace::') === 0)
will fix that just fine.
Fix what? If you write:
namespace My::Namespace;
function foo() {
$a = new DateTime();
}
then on each call to foo() autoloader for My::Namespace::DateTime would
be called, then it would go to disk and see if there's some file
implementing that class, search all include path for it and fail, and
only then use internal DateTime. That's not "just fine".
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Am 11.12.2007 um 23:38 schrieb Stanislav Malyshev:
A simple
if(strpos($className 'My::Namespace::') === 0)
will fix that just fine.Fix what? If you write:
namespace My::Namespace;
function foo() {
$a = new DateTime();
}then on each call to foo() autoloader for My::Namespace::DateTime
would be called, then it would go to disk and see if there's some
file implementing that class, search all include path for it and
fail, and only then use internal DateTime. That's not "just fine".
namespace Name::Space;
class Ship {
public static function __autoload($className) {
if(strpos($className, 'Name::Space::') === 0) {
// the real deal
}
}
}
...
spl_autoload_register(array('Name::Space::Ship', '__autoload'));
No disk access. And with my suggestion to allow limiting autoloaders
to certain namespaces, it would be cut down even further.
- David
namespace Name::Space;
class Ship {
public static function __autoload($className) {
if(strpos($className, 'Name::Space::') === 0) {
// the real deal
}
}
}...
spl_autoload_register(array('Name::Space::Ship', '__autoload'));
No disk access. And with my suggestion to allow limiting autoloaders to
I don't understand. Is your autoloader going to do any disk accesses at
all or it's just a stub that doesn't load any classes? If it does disk
access, it would do it on any internal class access inside namespace
Name::Space. Please explain me in detail how it could ever happen otherwise.
--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Am 12.12.2007 um 00:24 schrieb Stanislav Malyshev:
namespace Name::Space;
class Ship {
public static function __autoload($className) {
if(strpos($className, 'Name::Space::') === 0) {
// the real deal
}
}
}
...
spl_autoload_register(array('Name::Space::Ship', '__autoload'));
No disk access. And with my suggestion to allow limiting
autoloaders toI don't understand. Is your autoloader going to do any disk accesses
at all or it's just a stub that doesn't load any classes? If it does
disk access, it would do it on any internal class access inside
namespace Name::Space. Please explain me in detail how it could ever
happen otherwise.
I was assuming there was no need to explain that "// the real deal" is
where the class loading goes.
Look. If you have an autoloader for Your::Namespace, then you just
need to check if the class name (which is fully qualified, with the
entire namespace prefix in the name) starts with "Your::Namespace" to
prevent disk access.
David
Look. If you have an autoloader for Your::Namespace, then you just need
to check if the class name (which is fully qualified, with the entire
namespace prefix in the name) starts with "Your::Namespace" to prevent
disk access.
How this prevents disk access, I don't understand? So, it does start
with Your::Namespace, how now it is going to prevent disk access?
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Am 12.12.2007 um 01:02 schrieb Stanislav Malyshev:
Look. If you have an autoloader for Your::Namespace, then you just
need to check if the class name (which is fully qualified, with the
entire namespace prefix in the name) starts with "Your::Namespace"
to prevent disk access.How this prevents disk access, I don't understand? So, it does start
with Your::Namespace, how now it is going to prevent disk access?
Stas, please. It is preventing disk access in case the file to be
loaded is not from my namespace. If it is from my namespace, and I as
an autoloader was called, what am I gonna do? require() it of course,
what else? My point was that if you have ten autoloaders registered,
and the first nine of them cannot autoload the class, those nine disk
accesses can be prevented by checking at least the namespace.
- David
Stas, please. It is preventing disk access in case the file to be loaded
is not from my namespace. If it is from my namespace, and I as an
autoloader was called, what am I gonna do? require() it of course, what
else? My point was that if you have ten autoloaders registered, and the
If the class for which autoloaded request is issued exists. However,
we are discussing the case where this class does not exist, so it can
not be loaded. Thus, autoload request will be repeated on each access to
such class.
--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com