Version 1 and 2 two are the same, the place where we include other code does not influence naming rules in the current file. Why do we get instances of PHP's internal DateTime class instead of the one from Name::Space? Well, two things have to be considered:
1. We are in the global space, PHP will only look for DateTime in the global space.
2. The use-Statement declares that we want to create a shortcut to Name::Space, not to Name::Space::DateTime. If we wanted to use the class from Name::Space we would need to write $d = new Space::DateTime, which is version 3.
(We can not do a use Name::Space::DateTime here, this results in a fatal error. However, we could do use Name::Space::DateTime as DT and then write $d = new DT(), this will give instances of Name::Space::DateTime.)
With version 4 we have put our example code into its own namespace, but the result is still the same as in version 1 and 2. What's happening?
1. We are in namespace foo, and in namespace foo no class DateTime exists.
2. Our shortcut use Name::Space still does not refer to Name::Space::DateTime, to create instances from this class we still need to write $d = new Space::DateTime as in version 5. This means the class does not apply either in version 4.
3. As no further use declarations exist, PHP falls back to its internal DateTime class. (If this class would not exist, a call to the registered autoload function would be issued.)
Finally, version 6 gives the result we originally intended: The class Name::Space::DateTime is used instead of PHP's internal class. This is because we stated in the use declaration that we want to use Name::Space::DateTime as DateTime.
However, in the original posting of David Zülke in php internals he feared that the two instances of $d might be from different classes. Well, this might really happen under some circumstances. More after the break...
Lets put our example into the same namespace as our DateTime class:
$d = new DateTime();
$d = new DateTime();
Now the first and second $d are instances of different classes. What happened? On the first $d = new DateTime(), the class Name::Space::DateTime was not known, so PHP decided that only its internal DateTime class can be meant. But on the second $d = DateTime() the Name::Space::DateTime is known because it was loaded in someStuffWeDoNotHaveControlOver() and therefore takes precedence over the internal class.
What can be done to prevent this?
1. If you want to use the internal class, use new ::DateTime() instead.
2. If you want to use the class from the namespace, make sure PHP knows about this:
a) Load the class before.
b) Declare a use statement: use Name::Space::DateTime;
Yeah, that's what I actually meant I thought the resolution rules also applied to "use" in the same way, but that's nonsense of course, since you need to use at least one prefix there (use Name::Space; is the same as use Name::Space as Space).
In any case, glad to see the problem really exists as I thought. Now let's see what they intend to do about it - I think it's a quite a gotcha people need to be aware of. Has the potential for some serious WTF moments.