On Thu, 6 Dec 2007, Gregory Beaver wrote:

> I've been thinking a *lot* about your provocative email in the past
> couple of days, and have come to a different conclusion from my original
> reply (which, as a reminder stated I saw no problem with removing
> namespaces as long as we kept the import facility to alias classes via
> use).  After a few hours of thinking practically about the
> implementation, I realized that this would be impossible for the same
> reasons as your first argument.  So, I set out to find a solution that
> keeps namespaces and solves the problems.

Right, that was the idea behind the mail :) As yours is pretty long, I'm 
only going to respond to the main points.

> 1) recommend all global non-namespaced code that wishes to import
> namespaced code via "use Namespace::Classname" add a "namespace
> __php__;" at the top of the file, and that the __php__ namespace be
> reserved for use by end-user applications.
>
> 2) use Name::*; is technically impossible without some kind of
> autoloading mechanism, but can be reasonably approximated by importing a
> long namespace name as a shorter one.  "use PEAR2::Really::Long::Name as
> a;" then allows referring to PEAR2::Really::Long::Name::Classname as
> a::Classname, and PEAR2::Really::Long::Subnamespace::Classname as
> a::Subnamespace::Classname.
>
Yeah, I know... I don't really care about this myself anyway - it's just 
something that I heard in discussions.

[snip]
> 
> Detailed answers:
> 
> Derick Rethans wrote:
> > 1. As it is impossible to do "use XXX as NativeClass" we get to the 
> <snip>
> >    extension (DateTime, DateTimeZone). However introducing the new class
> >    DateTimeSpan might break people's code that do things like:
> > 
> >     <?php
> >     use myNamespace::DateTimeZone as DateTimeZone;
> >     ?>
> 
> This is indeed the biggest problem.  However, it only exists in the
> global "namespace" (non-namespaced code).  An example script using the
> non-existing hypothetical PEAR2::DateTime class:
> 
> <?php
> include 'PEAR2/Autoload.php';
> use PEAR2::DateTime; // fatal error - use name conflicts with internal class
> $a = new DateTime;
> ?>
> 
> However, the answer is simple and elegant.  PHP applications that take
> advantage of namespaces should use a namespace *in the application
> global code* that is reserved for application code, like __php__.
> 
> <?php
> namespace __php__;
> include 'PEAR2/Autoload.php';
> use PEAR2::DateTime;
> $a = new DateTime; // $a is an object of class PEAR2::DateTime after
> autoloading, or if a previously included file has declared class
> DateTime in namespace PEAR
> ?>
> 
> Note that the only difference here is the addition of 1 line of code at
> the top of the file.  On the same token, this code:
> 
> <?php
> namespace __php__;
> $a = new DateTime; // $a is an object of class ::DateTime
> ?>
> 
> works as expected, accessing the internal DateTime class directly.
> 
> In other words, 1 line of code is needed to take advantage of
> namespace's full protection and ability to import conflicting class
> names into the "global" (in this case unqualified, not containing :: in
> the name) scope, while at the same time preserving BC with existing code
> (no modification needed beyond addition of "namespace __php__;").
> 
> I recommend that the manual specify this convention, and will happily
> take on the documentation of it.

> > 2. You have to import every class yourself. You can currently not do:
> >    
> >     use myNamespace::* as *; // or similar syntax

[snip]
> 
> There are ways of simulating "use myNamespace::* as *;" that are almost
> as complete and are actually better for long-term maintenance.  For
> instance, let's say you want to use several classes from
> PEAR2::Ultra::Long::Package::Name.  You don't need to use each class
> individually, you can import the entire namespace:
> 
> <?php
> namespace __php__;
> use PEAR2::Ultra::Long::Package::Name;
> $a = new Name::ExampleClass;
> $b = new Name::SecondThing;
> $c = new Name::ThirdThing;
> ?>

Sounds like a good idea.

> I have no strong opinion on {}, but I do see a compelling argument in
> favor of not using {} for performance reasons if you're only going to
> use 1 namespace per file except in extraordinary circumstances.

The only thing that in the case you *have* a multi-namespace file, using 
braces would editors allow to the start and end of a namespace easily 
(f.e. VIM's %).

> A larger danger is this example:
> 
> <?php
> namespace foo;
> echo strlen('hi');
> include 'maliciousfile.php';
> echo strlen('hi');
> ?>
> 
> maliciousfile.php:
> <?php
> namespace foo;
> function strlen($a)
> {
>     // do bad stuff
>     echo "I'm evil"
>     return ::strlen($a);
> }
> ?>
> 
> The above script outputs "2I'm evil2" - foo::strlen() is called for the
> second call to strlen().

I thought only constants and classes could be parts of namespaces?

regards,
Derick

-- 
Derick Rethans
http://derickrethans.nl | http://ezcomponents.org | http://xdebug.org

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to