Hello,
following some discussions on the list (re. multiple namespaces in file)
as well as a short discussion on IRC regarding not being able to do
"use yeti::xml::DomDocument as DomDocument;" - I do not see any point in having
namespaces at all. And my excuses for the somewhat longish mail...
Some arguments:
-
As it is impossible to do "use XXX as NativeClass" we get to the
point where we'd have to namespace new internal native classes
otherwise we might introduce BC breaks. AFAIK, we've always said that
PHP reserves the globals space for it's own use (see also:
http://www.php.net/manual/en/userlandnaming.rules.php). In case we do
add new classes (an example could be DateTimeSpan), they should of
course follow the same format as already existing classes in the
extension (DateTime, DateTimeZone). However introducing the new class
DateTimeSpan might break people's code that do things like:<?php
use myNamespace::DateTimeZone as DateTimeZone;
?>feature versions of people would then show:
Fatal error: Cannot use myNamespace::DateTimeZone as DomDocument
because the name is already in use.It would be silly to require to have to do this:
- Create a class PHP::Date::TimeSpan
- In your scripts:
use PHP::Date::TimeSpan
But with the current implementation, this seems to be the only non-BC
breaking solution. If we chose not to require this silly namespacing
of internal classes, users instead have to do this:
<?php
use myNamespace::DateTimeZone as myDateTimeZone;
?>
Basically prefixing the classnames... This you can already do just
fine without namespaces.
-
You have to import every class yourself. You can currently not do:
use myNamespace::* as *; // or similar syntax
I understand why this is not implemented (runtime vs. compile time),
but it is a bit of a pain in the ass if you use lots of classes from
your own library f.e. -
We keep bickering over using { } or not, multiple namespaces in a
file or not... etc. I understand that people want more flexibility,
but also we need a simple to explain implementation. With the
current implementation I see the following problems here:- You can't stick multiple namespaces in one file
- Unlike other constructs in PHP that mark executable blocks,
namespaces don't use { }. - The "namespace" keyword at the start of a file is somewhat magic,
because it can only appear as first element in your script.
-
What is wrong with simple prefixes in the first place? Both PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.
With all the above considerations, especially my first point, I still have not
heard any good reason why namespaces in the current implementation are actually
useful - or what particular case they solve... so I am wondering, are they
really useful? I come now to the conclusion that they are not, and for myself
(and most likely my work projects) I would have to decide not to go with
namespaces, but instead stick with the 3 letter prefixing. Something that I
have totally no problem with, as it is nice and easy.
regards,
Derick
--
Derick Rethans
http://derickrethans.nl | http://ezcomponents.org | http://xdebug.org
With all the above considerations, especially my first point, I still have not
heard any good reason why namespaces in the current implementation are actually
useful - or what particular case they solve... so I am wondering, are they
really useful? I come now to the conclusion that they are not, and for myself
(and most likely my work projects) I would have to decide not to go with
namespaces, but instead stick with the 3 letter prefixing. Something that I
have totally no problem with, as it is nice and easy.
I hate to, but I agree. If the only point is to make class naming
pretty, it is kind of pointless. Give me namespaces that scope
variables to a file and then we have something. Yeah, I still code the
way PHP intended you to code, by templateing files together and not
making gynormous classes to print out some simple HTML over and over.
It would only be useful in that my company's code would not conflict
with some 3rd party software we use.
--
Brian Moon
Senior Developer
http://dealnews.com/
It's good to be cheap =)
I think namespaces are very useful when it comes to PHP in large scale
applications with hundreds of functions/classes.
With all the above considerations, especially my first point, I still have not
heard any good reason why namespaces in the current implementation are actually
useful - or what particular case they solve... so I am wondering, are they
really useful? I come now to the conclusion that they are not, and for myself
(and most likely my work projects) I would have to decide not to go with
namespaces, but instead stick with the 3 letter prefixing. Something that I
have totally no problem with, as it is nice and easy.I hate to, but I agree. If the only point is to make class naming
pretty, it is kind of pointless. Give me namespaces that scope
variables to a file and then we have something. Yeah, I still code the
way PHP intended you to code, by templateing files together and not
making gynormous classes to print out some simple HTML over and over.It would only be useful in that my company's code would not conflict
with some 3rd party software we use.--
Brian Moon
Senior Developerhttp://dealnews.com/
It's good to be cheap =)
Hi D,
extension (DateTime, DateTimeZone). However introducing the new class
DateTimeSpan might break people's code that do things like:<?php
use myNamespace::DateTimeZone as DateTimeZone;
?>
Typo? I guess you meant 'DateTimeSpan' to be in there somewhere...
This is I think the biggest problem with the implementation, that new
internal classes can still break userland code. The problem of single-file
namespacing is only a problem because of the performance implications for
those who bundle their includes, and it should be possible to find a good
way to resolve that. I don't really see a problem with the 'use only at the
head of the file' thing (although I know others do); in fact I prefer it,
because it makes for an easier upgrade path.
Can I just ask one thing? If namespace support is once again pulled before
it sees the light of a release, can we please document exactly what the
problems were, loud and clear, and put the document somewhere people are
likely to see it?
Thanks,
- Steph
Hi D,
extension (DateTime, DateTimeZone). However introducing the new class
DateTimeSpan might break people's code that do things like:<?php
use myNamespace::DateTimeZone as DateTimeZone;
?>Typo? I guess you meant 'DateTimeSpan' to be in there somewhere...
This is I think the biggest problem with the implementation, that new
internal classes can still break userland code. The problem of single-file
namespacing is only a problem because of the performance implications for
those who bundle their includes, and it should be possible to find a good
way to resolve that. I don't really see a problem with the 'use only at the
head of the file' thing (although I know others do); in fact I prefer it,
because it makes for an easier upgrade path.Can I just ask one thing? If namespace support is once again pulled before
it sees the light of a release, can we please document exactly what the
problems were, loud and clear, and put the document somewhere people are
likely to see it?Thanks,
- Steph
--
I never thought it would get back to the drawing board that way, but
Derick, as I said on irc when we discussed about that, I agree with
you. With the current implementation, the namespaces should be removed
completely. Not only because it has missing features, but from the
voice that comes out of the community, it seems that some features
(important ones) (Point 2) and some PHP general concept (Point 3) are
simply not what people want.
I do not want to start a flamewar here, but again, the { } thread came
up a few days ago and again, everyone who says that they get a
performance gain by aggregating the files (Like compiled PHP files)
are being either ignored or in some way insulted... Anyways, some
people do not believe in the aggregation of the files, why's that ? I
am not quite sure, well I have a few ideas but they are not
appropriate for the mailing list, but the optimization technique that
is aggregating the files work and I would really love to see it stay
(At least the ability to decide if I want to aggregate them or not).
And this is currently not possible with the implementation.
Things like use * as * is something that is missing and a very
important feature to my eyes as well. However, this kind of feature
comes with education. If we allow people to use * as *, we have to
explain them that the namespaces are not going to be coding for you.
They might introduce the same conflicting errors as before when they
had only classes. I want to make sure people understand that
namespaces are not there to make one type less but as a great man once
said, an additional structural element that is to be used correctly in
order to work correctly.
(You can give a nail to someone and he'll stick it in his eye instead
of building a house... but if you show him how to use the nail
correctly and with which other tools, he'll be able to build something
solid... maybe...)
From what I have experienced since the namespaces are in, my prefixing
is still the way to go to make sure I can run all my nifty
optimization scripts around and make a few "free" optimizations.
This is a thread that will probably go deep in the sand in a few days
(unless the community arises (which doesn't usually happen)) but for
the records, if anyone has anything to say, it's still the time :)
--
David Coallier,
Founder & Software Architect,
Agora Production (http://agoraproduction.com)
51.42.06.70.18
up a few days ago and again, everyone who says that they get a
performance gain by aggregating the files (Like compiled PHP files)
are being either ignored or in some way insulted... Anyways, some
That's the first time I hear asking somebody to help reproducing his
benchmark is an insult. But how it has anything to do with removing
namespaces?
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Can I just ask one thing? If namespace support is once again pulled
before it sees the light of a release, can we please document
exactly what the problems were, loud and clear, and put the
document somewhere people are likely to see it?
Amen. I wish we would do that for every decision we make that was
remotely controversial. Such summaries should link together all
relevant posts with a short summary. This is what I was talking about
before I left for Brazil. I think taking the approach to tag posts +
then being able to write some commentary would be a good solution for
this that could work out without too much reliance on a single person
putting in a fixed amount of time per week.
regards,
Lukas
Derick Rethans wrote:
With all the above considerations, especially my first point, I still have not
heard any good reason why namespaces in the current implementation are actually
useful - or what particular case they solve... so I am wondering, are they
really useful? I come now to the conclusion that they are not, and for myself
(and most likely my work projects) I would have to decide not to go with
namespaces, but instead stick with the 3 letter prefixing. Something that I
have totally no problem with, as it is nice and easy.
I have to agree with all points except for the usefulness of "use" - the
ability to re-alias classes is very nice.
Incidentally, one argument - that you can't alias internal classes - is
incorrect. Try this script:
<?php
namespace test;
use xmlreader as test;
class xmlreader {}
?>
However, in the global scope (no namespace) it would fail. This is a
bug that is easily fixed. use should allow re-aliasing of global
classes, and I could provide a very easy fix.
What if we simply kept the ability to alias classes via "use"? The best
feature of the current namespace implementation is the ability to rename
classes in a script. This way, you could use conflicting class names,
as in this example:
file1.php:
<?php
class DB {}
?>
file2.php:
<?php
import DB as Other_DB;
include 'file1.php';
class DB extends Other_DB {}
?>
All the benefits of namespaces with none of the brackets or no brackets
debate.
Greg
However, in the global scope (no namespace) it would fail. This is a
bug that is easily fixed. use should allow re-aliasing of global
classes, and I could provide a very easy fix.
This is not a bug - since there you work with test::xmlreader, which of
course you can define. But in global space you'd work with existing name
xmlreader, which would be redefined. And PHP never allowed redefining
classes.
file1.php:
<?php
class DB {}
?>file2.php:
<?php
import DB as Other_DB;
include 'file1.php';
class DB extends Other_DB {}
?>
You mean 'use' should kill the old name? I don't think it's a good idea
- we'd have to keep track of killed names, and since class can be named
in a lot of ways - i.e. if you have name A::B::C::D you can alias any
part of name, it would become messy.
Why exactly you need to rename existing classes?
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
However, in the global scope (no namespace) it would fail. This is a
bug that is easily fixed. use should allow re-aliasing of global
classes, and I could provide a very easy fix.This is not a bug - since there you work with test::xmlreader, which of
course you can define. But in global space you'd work with existing name
xmlreader, which would be redefined. And PHP never allowed redefining
classes.
I'm truly glad you said that's not a bug, my world just started to make
sense again. But Stas, consider (old dialect bc I need to update locally
sorry):
import nstest::test as whatever;
This works in the global space, right? Now along comes, say, Pierre or
Derick or Marcus with this class they just have to add to an existing
(non-namespaced) core extension, and the obvious and perfect name for this
class happens to be 'whatever'. I upgrade PHP and suddenly I start seeing
Fatal error: Import name 'whatever' conflicts with defined class in ...
Now sure, I can fix that. I can search and replace all my instances of
'whatever' in my code. How is that different from what we had before?
Greg would say I should've namespaced this file, I know... but it's possible
to use import (OK, 'use' now) in the global space, so how are you going to
prevent people from doing that?
- Steph
sense again. But Stas, consider (old dialect bc I need to update locally
sorry):import nstest::test as whatever;
This works in the global space, right? Now along comes, say, Pierre or
Right.
Derick or Marcus with this class they just have to add to an existing
(non-namespaced) core extension, and the obvious and perfect name for
this class happens to be 'whatever'. I upgrade PHP and suddenly I start
seeing
Right again. The thing is this problem can not be solved. You can not
both put all your classes into global namespace and expect them never to
clash even when you name two of them by the same name. That's like you
would talk in a language where all words would be "marklar" and expect
me to understand you :)
So what we can do is to avoid getting into such problem by using some
rules. I'd propose these rules:
- Namespace your libraries
- Do not import the class name into global space, but only library name.
Meaning, if your class is nstest::test, there's nothing wrong with
saying just so, if you are concerned about clashes. That's not worse
than you has nstest_test previously. But if you had PEAR::DB::Connection
and PEAR::DB::Connection::Data and PEAR::DB::Connection::Exception and
PEAR::DB::Query::Term and PEAR::DB::Query::Result, then you could do:
use PEAR::DB as myDB;
use PEAR::DB::Query as myQuery;
and you'd have to do much less work: just myQuery::Term and
myQuery::Result.
Now sure, I can fix that. I can search and replace all my instances of
'whatever' in my code. How is that different from what we had before?
If you insist on putting everything into globals space - it won't be. We
just give you the option of not doing it.
Greg would say I should've namespaced this file, I know... but it's
possible to use import (OK, 'use' now) in the global space, so how are
you going to prevent people from doing that?
I can't. I can only hope they would do it right, I can't force them to
do it right :)
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
I can't. I can only hope they would do it right, I can't force them to do
it right :)
I guess what I'm really asking is, 'is there any point in allowing
import/use to be used in the global space?' I'm tired and etc, but I just
can't visualize where it would be useful.
Maybe one of the OO gang could put me straight here?
- Steph
--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
I guess what I'm really asking is, 'is there any point in allowing
import/use to be used in the global space?' I'm tired and etc, but I just
can't visualize where it would be useful.
And now I've finished reading old South Park episodes...
OK, it's sinking in now. Because global import/use is something you only
have to type once, whereas you'd have to add the namespace declaration, the
relevant includes and any specific imports from the global namespace on a
per-file basis (unless that last is a bug in my ageing PHP copy).
Sorry, I'm slower than the average glacier tonight :(
Even so... if you want your code to be safe from potential naming collisions
you'd need to do all that stuff anyway, so what's the point in having a
quick and dirty way to be unsafe? What am I missing here? Surely if people
don't want to utilize namespacing in their own code they should just stick
with fully qualified names?
I'm asking a lot of questions because I'd like this to work, I just don't
see it as working if it's possible to break a namespaced application with
third-party changes. To me that's the main reason for having namespace
support in the first place, and without it, namespace support is just a way
to prettify names.
I'd like wildcard support too... and support for multiple namespaces per
file (for bundling only)... but neither of those are complete deal-breakers
in my eyes. Protection from naming collisions, is.
- Steph
I'd like wildcard support too... and support for multiple namespaces
per file (for bundling only)... but neither of those are complete
deal-breakers in my eyes. Protection from naming collisions, is.
FULLACK, the good news is that i accidently mailed Gregory off-list
yesterday and he seems to have a good solution.
Hello Steph,
Wednesday, December 5, 2007, 2:33:47 AM, you wrote:
However, in the global scope (no namespace) it would fail. This is a
bug that is easily fixed. use should allow re-aliasing of global
classes, and I could provide a very easy fix.This is not a bug - since there you work with test::xmlreader, which of
course you can define. But in global space you'd work with existing name
xmlreader, which would be redefined. And PHP never allowed redefining
classes.
I'm truly glad you said that's not a bug, my world just started to make
sense again. But Stas, consider (old dialect bc I need to update locally
sorry):
import nstest::test as whatever;
This works in the global space, right? Now along comes, say, Pierre or
Derick or Marcus with this class they just have to add to an existing
(non-namespaced) core extension, and the obvious and perfect name for this
class happens to be 'whatever'. I upgrade PHP and suddenly I start seeing
Fatal error: Import name 'whatever' conflicts with defined class in ...
There is no technical reason for this. If this is true I am strongly against
namespaces at all because then there is nothing usefull left.
Best regards,
Marcus
Von: Steph Fox [mailto:steph@zend.com]
Gesendet: Mittwoch, 5. Dezember 2007 02:34
import nstest::test as whatever;
This works in the global space, right? Now along comes, say, Pierre or
Derick or Marcus with this class they just have to add to an existing
(non-namespaced) core extension, and the obvious and perfect name for
this
class happens to be 'whatever'. I upgrade PHP and suddenly I start
seeingFatal error: Import name 'whatever' conflicts with defined class in ...
Indeed it's pretty pointless if future additions to the core break (namespace-aware) code that previously worked.
I am probably alone with that point of view, but: Given that it was technically feasible, (future) core classes should be in namespaces as well.
The whole namespace thing depends on that everybody (users, library providers and the core) collaborates and puts "their" stuff in "their" namespace so that everyone can decide in "their" file which classes are needed.
Global namespace is precious, so let the user decide which classes to have there.
For the same reason, supporting "use Library::*" is a bad idea because that might break working code the same way as above if the Library introduces a new class.
-mp.
Matthias Pigulla schrieb:
Given that it was technically feasible, (future) core classes should
be in namespaces as well.
Or
- Introduce namespaces in PHP 6
- Move all functions and classes that are now global into
(per-extension) namespace(s) - Add a fallback mechanism that looks up
mysqli_query()
as query()
in the MySQLi extension's namespace for PHP 6.0, drop that BC
layer in PHP 6.1
Not saying that I would want this (I don't think I do), just mentioning
the option.
--
Sebastian Bergmann http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69
This would be a good idea, if implemented with a compatibility layer to
be removed later.
::php
::str
::arr
::ob
etc
::ext
::mysql
::mysqli
Userland code can then use a namespace such as ::app, or just use the
global namespace with no worries. Probably not going to happen, atleast
not for a while, due to compatibility issues, but just a thought.
Matthias Pigulla schrieb:
Given that it was technically feasible, (future) core classes should
be in namespaces as well.Or
- Introduce namespaces in PHP 6
- Move all functions and classes that are now global into
(per-extension) namespace(s)- Add a fallback mechanism that looks up
mysqli_query()
as query()
in the MySQLi extension's namespace for PHP 6.0, drop that BC
layer in PHP 6.1Not saying that I would want this (I don't think I do), just mentioning
the option.--
Sebastian Bergmann http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69
Matthias Pigulla schrieb:
Given that it was technically feasible, (future) core classes should
be in namespaces as well.Or
- Introduce namespaces in PHP 6
- Move all functions and classes that are now global into
(per-extension) namespace(s)- Add a fallback mechanism that looks up
mysqli_query()
as query()
in the MySQLi extension's namespace for PHP 6.0, drop that BC
layer in PHP 6.1
What about adding namespaced aliases for internal classes as a start
(basically: class spl::FileInfo extends SplFileInfo) and drop the old
names (SplFileInfo) in PHP6 and keep only the new ones.
However, in the global scope (no namespace) it would fail. This is a
bug that is easily fixed. use should allow re-aliasing of global
classes, and I could provide a very easy fix.
No, use should not allow this. Take the following example:
<?php
namespace blah;
use DomDocument as test;
class DOMDocument { }
$dom = new DOMDocument; //
$dom->loadXML('<books><book><title>blah</title></book></books>');
$s = simplexml_import_dom($dom);
echo $s->book[0]->title; // blah
?>
Besides this being a big WTF factor (why is my internal class
suddendly doing something else?) simplexml will horrible fail in this
case.
Derick
--
Derick Rethans
http://derickrethans.nl | http://ezcomponents.org | http://xdebug.org
I don't understand what are you going to demonstrate with this example.
Did you try to run it?
It produces error as expected.
DOMDocument() in your example is a user-space class that is not related
to internal ext/dom class. If you like to use internal class that is
overriden in namespace you can use ::DomDocument instead.
The "use DomDocument as test;" is useless from my point of view.
You always may override internal classes in namespaces.
Thanks. Dmitry.
Derick Rethans wrote:
However, in the global scope (no namespace) it would fail. This is a
bug that is easily fixed. use should allow re-aliasing of global
classes, and I could provide a very easy fix.No, use should not allow this. Take the following example:
<?php
namespace blah;
use DomDocument as test;class DOMDocument { }
$dom = new DOMDocument; //
$dom->loadXML('<books><book><title>blah</title></book></books>');
$s = simplexml_import_dom($dom);echo $s->book[0]->title; // blah
?>Besides this being a big WTF factor (why is my internal class
suddendly doing something else?) simplexml will horrible fail in this
case.Derick
I used import in my last example instead of use, that was simply a typo,
not trying to open a can of worms.
Sorry,
Greg
following some discussions on the list (re. multiple namespaces in file)
as well as a short discussion on IRC regarding not being able to do
"use yeti::xml::DomDocument as DomDocument;" - I do not see any point in having
You mean like ability to override existing classes? I think it could be
done but I don't see it as a good idea - it probably would lead to some
weird programming mistakes.
- As it is impossible to do "use XXX as NativeClass" we get to the
point where we'd have to namespace new internal native classes
otherwise we might introduce BC breaks. AFAIK, we've always said that
There's very easy solution to this, if it ever becomes a problem - using
two-component names.
You have to import every class yourself. You can currently not do:
use myNamespace::* as *; // or similar syntax
Right, you can't - but you can use two-component names, i.e.
myNamespace::Name.
- We keep bickering over using { } or not, multiple namespaces in a
file or not... etc. I understand that people want more flexibility,
but also we need a simple to explain implementation. With the
That's why not all flexibility gets in.
- You can't stick multiple namespaces in one file
You are not supposed to unless you using it as performance solution,
which is rather dubious practice anyway.
- Unlike other constructs in PHP that mark executable blocks,
namespaces don't use { }.
That's because namespaces are not executable blocks.
- The "namespace" keyword at the start of a file is somewhat magic,
because it can only appear as first element in your script.
Yes, it is somewhat magic, because it changes how names behave. If the
whole thread is really reincarnation of the braces theme - I think you
could just link to the archive, as I don't see any arguments here that
weren't discussed to death three times.
- What is wrong with simple prefixes in the first place? Both PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.
What is wrong is names like
PEAR_DB_Data_Database_Module_Adapter_Implementation_Interface_Exception_Information_Collection_Element.
When you write a code that uses such names, you really don't want to
repeat all the thing every time.
useful - or what particular case they solve... so I am wondering, are they
really useful? I come now to the conclusion that they are not, and for myself
Yes, they are.
(and most likely my work projects) I would have to decide not to go with
namespaces, but instead stick with the 3 letter prefixing. Something that I
Well, the loss is all yours :)
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
following some discussions on the list (re. multiple namespaces in file) as
well as a short discussion on IRC regarding not being able to do
"use yeti::xml::DomDocument as DomDocument;" - I do not see any point in
havingYou mean like ability to override existing classes? I think it could be done
but I don't see it as a good idea - it probably would lead to some weird
programming mistakes.
Of course, I think allowwing this is a really bad idea - which brings me
to the main point of this argument:
- As it is impossible to do "use XXX as NativeClass" we get to the point
where we'd have to namespace new internal native classes
otherwise we might introduce BC breaks. AFAIK, we've always said thatThere's very easy solution to this, if it ever becomes a problem - using
two-component names.
And that is exactly what I think we should not do. PHP reserves the
global scope. period. That means that (core)extensions should not have
to deal with all sorts of namespace clue or other tricks just because
some people like a "misguided" implementation of namespaces. The idea of
namespaces is to prevent collisions in USER land code, not turning
internal PHP classes into a pile of goo.
- We keep bickering over using { } or not, multiple namespaces in a
file or not... etc. I understand that people want more flexibility,
but also we need a simple to explain implementation. With theThat's why not all flexibility gets in.
- You can't stick multiple namespaces in one file
You are not supposed to unless you using it as performance solution, which is
rather dubious practice anyway.
You're not supposed to put a count($array) inside your for loop either.
I don't quite understand why allowing multiple namespaces is such a big
issue, however - it won't solve the naming collision issue.
- Unlike other constructs in PHP that mark executable blocks,
namespaces don't use { }.That's because namespaces are not executable blocks.
Neither are classes.
- What is wrong with simple prefixes in the first place? Both PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.What is wrong is names like
PEAR_DB_Data_Database_Module_Adapter_Implementation_Interface_Exception_Information_Collection_Element.
When you write a code that uses such names, you really don't want to repeat
all the thing every time.
No, but, do you really need to have such long names? And besides that,
you have to keep repeating them in every file you'd want to use them -
which means you actually have to type more in some places. So this
argument is kind of lame.
useful - or what particular case they solve... so I am wondering, are they
really useful? I come now to the conclusion that they are not, and for
myselfYes, they are.
Just saying "Yes, they are" is not a very good argument - actually, it's
not an argument at all.
(and most likely my work projects) I would have to decide not to go with
namespaces, but instead stick with the 3 letter prefixing. Something that IWell, the loss is all yours :)
Actually, it's exactly the opposite, as I avoid naming colissions
(point 1), I don't need to import every class I want to use (point 2),
and can group all my classes together in one file (point 3).
regards,
Derick
--
Derick Rethans
http://derickrethans.nl | http://ezcomponents.org | http://xdebug.org
some people like a "misguided" implementation of namespaces. The idea of
namespaces is to prevent collisions in USER land code, not turning
internal PHP classes into a pile of goo.
Yes, idea of namespaces is not to turn PHP classes into a pile of goo.
But what's your point?
I don't quite understand why allowing multiple namespaces is such a big
issue, however - it won't solve the naming collision issue.
I'm sorry, I don't understand what you mean by "multiple namespaces" -
multiple namespaces per file? I object to allowing it for reasons having
absolutely nothing to do with naming collisions, as anybody bothering to
actually read what I wrote would immediately know.
That's because namespaces are not executable blocks.
Neither are classes.
Your point being?
No, but, do you really need to have such long names? And besides that,
Yes. Such names are hard fact of life, I have seen them in many
applications and libraries, and I have heard developers to complain
about it.
you have to keep repeating them in every file you'd want to use them -
Once per file, yes. Much better than having to spell out all the long
names every time.
Just saying "Yes, they are" is not a very good argument - actually,
it's
not an argument at all.
No more and no less than "I wonder if they are useful, let's just delete
them".
Actually, it's exactly the opposite, as I avoid naming colissions
(point 1), I don't need to import every class I want to use (point 2),
and can group all my classes together in one file (point 3).
Of course, if you don't want to hear about namespaces, nobody can force
you. However, all of your points (avoiding naming collisions, not
needing to import every class you want to use and ability to group
classes together) is exactly how namespaces work right now. If you
refuse to learn about it, it can't be helped, however that just means
you deny yourself a very useful tool.
--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
+1 for putting namespaces on the backburner and taking the time to
get it 100% right ...
Stanislav Malyshev wrote:
some people like a "misguided" implementation of namespaces. The idea
of namespaces is to prevent collisions in USER land code, not turning
internal PHP classes into a pile of goo.Yes, idea of namespaces is not to turn PHP classes into a pile of goo.
But what's your point?I don't quite understand why allowing multiple namespaces is such a
big issue, however - it won't solve the naming collision issue.I'm sorry, I don't understand what you mean by "multiple namespaces" -
multiple namespaces per file? I object to allowing it for reasons having
absolutely nothing to do with naming collisions, as anybody bothering to
actually read what I wrote would immediately know.
this implies that your objections to multiple namespaces per file is valid
whereas objections to the limitation are invalid.
apparently people keep 'flogging this horse to death' because they are not
convinced by your wisdom with regard to this decision - they may be idiots (me included)
but they are the majority of your users, so it seems.
That's because namespaces are not executable blocks.
Neither are classes.
Your point being?
that therefore your argue that "namespaces are not executable blocks" doesn't
hold up unless your willing to state the inconsistency is one of your design goals.
<remark type="OT" class="irrelevant"> developers will complain, it's in their blood, nothing anyone will ever produce will change that ... somewhere in the future when all code is created without the intervention of man .. even then there will still be a compiler complaining. </remark>No, but, do you really need to have such long names? And besides that,
Yes. Such names are hard fact of life, I have seen them in many
applications and libraries, and I have heard developers to complain
about it.
you have to keep repeating them in every file you'd want to use them -
Once per file, yes. Much better than having to spell out all the long
names every time.Just saying "Yes, they are" is not a very good argument - actually, it's
not an argument at all.No more and no less than "I wonder if they are useful, let's just delete
them".
actually that is not true - a halfbaked concept is pretty much garanteed to give you
and the users of your product more headaches than no implementation at all. and
once the genie is out of the bottle your stuck with it - with all the BC implications
of having to support functionality people would rather see changed.
besides possibly having to type a little less, there seems to be nothing namespaces would
give us [in it's current form] that we cannot achieve already ... with the bonus that
users are currently not restricted in the way they organize/rollout their code, at least
with regard to 'bundling' of files.
Actually, it's exactly the opposite, as I avoid naming colissions
(point 1), I don't need to import every class I want to use (point 2),
and can group all my classes together in one file (point 3).Of course, if you don't want to hear about namespaces, nobody can force
you. However, all of your points (avoiding naming collisions, not
needing to import every class you want to use and ability to group
classes together) is exactly how namespaces work right now. If you
refuse to learn about it, it can't be helped, however that just means
you deny yourself a very useful tool.
conversly - when namespace functionality is released, every developer will be confronted
with any problems they might bring with them, at some stage, because there will be third
party code out there that uses namespaces (code which for the sake of argument one would
be required to use under some circumstances).
+1 for putting namespaces on the backburner and taking the time to
get it 100% right ...
What's "100% right"? Any proposals (besides braces)?
apparently people keep 'flogging this horse to death' because they are not
convinced by your wisdom with regard to this decision - they may be idiots (me included)
I never talked about "idiots". I know smart people can have different
opinions, and - oh horror! - some may have wrong or mistaken opinions
too, and that doesn't make them idiots. How about you?
actually that is not true - a halfbaked concept is pretty much garanteed to give you
and the users of your product more headaches than no implementation at all. and
This concept, however, is not "halfbaked".
besides possibly having to type a little less, there seems to be nothing namespaces would
give us [in it's current form] that we cannot achieve already ... with the bonus that
Yes there is. More structured and clean code.
conversly - when namespace functionality is released, every developer will be confronted
with any problems they might bring with them, at some stage, because there will be third
party code out there that uses namespaces (code which for the sake of argument one would
be required to use under some circumstances).
These problems being?
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Stanislav Malyshev wrote:
+1 for putting namespaces on the backburner and taking the time to
get it 100% right ...What's "100% right"? Any proposals (besides braces)?
I'll take a guess that you put alot of effort into the namespace implementation,
that's the only reason I can think of that your taking it all so personally and
being rather vitriol.
for the sake of your health take a step back and breath my friend. you are
not the car you drive, the clothes you wear or the namespace implementation you
created :-)
apparently people keep 'flogging this horse to death' because they are
not
convinced by your wisdom with regard to this decision - they may be
idiots (me included)I never talked about "idiots". I know smart people can have different
opinions, and - oh horror! - some may have wrong or mistaken opinions
too, and that doesn't make them idiots. How about you?
it was a self effacing comment. I think it's safe to say that compared to
most of the php devs, I, and people like me could be considered idiots at
least as far as developing is concerned .. it's all relative besides which
the key words were "may be".
actually that is not true - a halfbaked concept is pretty much
garanteed to give you
and the users of your product more headaches than no implementation at
all. andThis concept, however, is not "halfbaked".
based on the reactions it has been recieving I would disagree. that is not to say
that completing the baking process would not result in a wonderful functional addition
to the language. I'm just advocating putting it on the backburner until the cooking
time is complete.
"halfbaked" is probably the wrong word - it has negative conatations that I didn't
mean to imply.
besides possibly having to type a little less, there seems to be
nothing namespaces would
give us [in it's current form] that we cannot achieve already ... with
the bonus thatYes there is. More structured and clean code.
you have metrics to back that up? of course not because it's a completely subjective
point of view - and many people seem to think that there is no real gain in this respect,
besides there is nothing to stop me writing namespaced spaghetti.
I agree that namespaces pontentially offer a tool that allows developers to create
clearer structure in their code but given that it's only a potential why not take a time
out to hammer out more details, get more consensus and work out the details of where
namespacing should go in terms of functionality with the hassle of having to worry about BC.
conversly - when namespace functionality is released, every developer
will be confronted
with any problems they might bring with them, at some stage, because
there will be third
party code out there that uses namespaces (code which for the sake of
argument one would
be required to use under some circumstances).These problems being?
no longer having the option of bundling files for performance reasons is one example, personally
I have never done anything like that but apparently other people do and with positive results for
their applications - to me it seems that forcing such a restriction on these people is against the
pragmatic philosophy that [hopefully still] drives php, and is rather artificial.
I didn't put any work in here and I agree with him 100%. Namespaces have
been incredibly useful for me. Now that I'm using them I would not want
to do without them.
As far as bundling, my application (over 11,000 lines now) did use a
bundling feature that I can no longer use. It would be very nice to be
able to do this, but honestly it is worth the performance hit to me.
Any large application needs structure, and yes underscores can be used
but this is a pain typing out long names every time, and what's the
harm? If you want to use bundling or don't like namespaces then just
don't use them.
Stanislav Malyshev wrote:
+1 for putting namespaces on the backburner and taking the time to
get it 100% right ...What's "100% right"? Any proposals (besides braces)?
I'll take a guess that you put alot of effort into the namespace implementation,
that's the only reason I can think of that your taking it all so personally and
being rather vitriol.for the sake of your health take a step back and breath my friend. you are
not the car you drive, the clothes you wear or the namespace implementation you
created :-)apparently people keep 'flogging this horse to death' because they are
not
convinced by your wisdom with regard to this decision - they may be
idiots (me included)I never talked about "idiots". I know smart people can have different
opinions, and - oh horror! - some may have wrong or mistaken opinions
too, and that doesn't make them idiots. How about you?it was a self effacing comment. I think it's safe to say that compared to
most of the php devs, I, and people like me could be considered idiots at
least as far as developing is concerned .. it's all relative besides which
the key words were "may be".actually that is not true - a halfbaked concept is pretty much
garanteed to give you
and the users of your product more headaches than no implementation at
all. andThis concept, however, is not "halfbaked".
based on the reactions it has been recieving I would disagree. that is not to say
that completing the baking process would not result in a wonderful functional addition
to the language. I'm just advocating putting it on the backburner until the cooking
time is complete."halfbaked" is probably the wrong word - it has negative conatations that I didn't
mean to imply.besides possibly having to type a little less, there seems to be
nothing namespaces would
give us [in it's current form] that we cannot achieve already ... with
the bonus thatYes there is. More structured and clean code.
you have metrics to back that up? of course not because it's a completely subjective
point of view - and many people seem to think that there is no real gain in this respect,
besides there is nothing to stop me writing namespaced spaghetti.I agree that namespaces pontentially offer a tool that allows developers to create
clearer structure in their code but given that it's only a potential why not take a time
out to hammer out more details, get more consensus and work out the details of where
namespacing should go in terms of functionality with the hassle of having to worry about BC.conversly - when namespace functionality is released, every developer
will be confronted
with any problems they might bring with them, at some stage, because
there will be third
party code out there that uses namespaces (code which for the sake of
argument one would
be required to use under some circumstances).These problems being?
no longer having the option of bundling files for performance reasons is one example, personally
I have never done anything like that but apparently other people do and with positive results for
their applications - to me it seems that forcing such a restriction on these people is against the
pragmatic philosophy that [hopefully still] drives php, and is rather artificial.
based on the reactions it has been recieving I would disagree. that is not to say
that completing the baking process would not result in a wonderful functional addition
to the language. I'm just advocating putting it on the backburner until the cooking
time is complete.
So far I have yet to see an improvement proposal except for:
- Let's do it with braces
and - Multiple namespaces per file.
Neither of these doesn't make the concept "half-baked" if it's decided
on either side - first being tiny syntax detail blown entirely out of
proportion and second being technicality of little use for most people
except for sites engaging in exotic performance practices they better
didn't. Both do not have much to do with the conceptual level.
you have metrics to back that up? of course not because it's a completely subjective
Metrics of what?
I agree that namespaces pontentially offer a tool that allows developers to create
clearer structure in their code but given that it's only a potential why not take a time
Sure it's only a potential - there's no released PHP version with
namespaces. Only way to hammer out practical namespaces issues is to
start using them, and that doesn't happen until - well, we start using
them.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Stanislav Malyshev wrote:
based on the reactions it has been recieving I would disagree. that is
not to say
that completing the baking process would not result in a wonderful
functional addition
to the language. I'm just advocating putting it on the backburner
until the cooking
time is complete.So far I have yet to see an improvement proposal except for:
- Let's do it with braces
and- Multiple namespaces per file.
Neither of these doesn't make the concept "half-baked" if it's decided
on either side - first being tiny syntax detail blown entirely out of
proportion and second being technicality of little use for most people
except for sites engaging in exotic performance practices they better
didn't. Both do not have much to do with the conceptual level.\
even after I explained my [possibly dubious] use of the word "half-baked"
you seem to feel compelled to focus on the negative emotions the word
triggers. "half-baked" was the wrong word.
you can't use a concept unless it's implemented - and we are arguing the
implementation [details] not the concept. I believe that the implementation
needs a little ironing out ... what's the harm in taking the time to do this?
or at least taking the time to let consensus take hold?
you have metrics to back that up? of course not because it's a
completely subjectiveMetrics of what?
metrics that support your argument that namespaces will make code more
maintainable, offer better structure and cleaner code.
it was a rethorical question obviously because what consitutes better
structure, code cleaniness and maintainability are subjective to say the
least. I don't expect you to come up with any and I agree that namespaces
do have the potential to help in this area.
I agree that namespaces pontentially offer a tool that allows
developers to create
clearer structure in their code but given that it's only a potential
why not take a timeSure it's only a potential - there's no released PHP version with
namespaces. Only way to hammer out practical namespaces issues is to
start using them, and that doesn't happen until - well, we start using
them.
it remains nothing more than a pontential even after release. in the same
way that php itself has the potential to enable web developers to be fast and
flexible in their implementations.
this thread is proof enough that practical issues can be raised and
hammered out before release .. granted the chance that you cover every edge
case is unlikely.
implementation [details] not the concept. I believe that the implementation
needs a little ironing out ... what's the harm in taking the time to do this?
or at least taking the time to let consensus take hold?
No harm, but we will have multiple namespaces per file figured out
pretty soon, and I don't see any new developments with the braces thing,
so what exactly would we wait for?
metrics that support your argument that namespaces will make code more
maintainable, offer better structure and cleaner code.
Obviously, we can't have any metrics of anything until the namespaces
are implemented and used in some serious project, which can't happen
until we have a release with namespaces in it.
it remains nothing more than a pontential even after release. in the
same
For some time, yes. And if one chooses not to use it, maybe forever for
that particular user.
I'm all for discussing practical ones, but frankly I don't see any new
issues here worth delaying anything.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
The implementation as it is now works. It's functional, and useful.
Minor issues like import/use can be worked out when necessary, but for
now I see this as something that can be released (provided that most of
the bugs are worked out). Multiple namespaces per file is the only thing
I see as a feature that should be added, but as of now it is not a
pressing issue.
implementation [details] not the concept. I believe that the implementation
needs a little ironing out ... what's the harm in taking the time to do this?
or at least taking the time to let consensus take hold?No harm, but we will have multiple namespaces per file figured out
pretty soon, and I don't see any new developments with the braces thing,
so what exactly would we wait for?metrics that support your argument that namespaces will make code more
maintainable, offer better structure and cleaner code.Obviously, we can't have any metrics of anything until the namespaces
are implemented and used in some serious project, which can't happen
until we have a release with namespaces in it.it remains nothing more than a pontential even after release. in the
sameFor some time, yes. And if one chooses not to use it, maybe forever for
that particular user.
I'm all for discussing practical ones, but frankly I don't see any new
issues here worth delaying anything.Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Stanislav Malyshev wrote:
implementation [details] not the concept. I believe that the
implementation
needs a little ironing out ... what's the harm in taking the time to
do this?
or at least taking the time to let consensus take hold?No harm, but we will have multiple namespaces per file figured out
pretty soon, and I don't see any new developments with the braces
thing, so what exactly would we wait for?metrics that support your argument that namespaces will make code more
maintainable, offer better structure and cleaner code.Obviously, we can't have any metrics of anything until the namespaces
are implemented and used in some serious project, which can't happen
until we have a release with namespaces in it.it remains nothing more than a pontential even after release. in
the sameFor some time, yes. And if one chooses not to use it, maybe forever
for that particular user.
I'm all for discussing practical ones, but frankly I don't see any new
issues here worth delaying anything.
Hey Stas,
I just felt the need to send a note in to say thank you for working to
keep the namespaces implementation in. I've been developing toward PHP
5.3 and would be sorely disappointed if I had to re-write all of my
libraries to remove the use of namespaces.
So, thanks.
implementation [details] not the concept. I believe that the
implementation needs a little ironing out ... what's the harm in taking
the time to do this? or at least taking the time to let consensus take
hold?No harm, but we will have multiple namespaces per file figured out
pretty soon, and I don't see any new developments with the braces thing,
so what exactly would we wait for?
Actually, as I've said previously IF we switch to multiple namespaces per file
(which I honestly have no strong opinion on), switching to braces at the same
time makes sense. It's much easier to parse visually (by a human) in that
case, and there's no reason I know of why we couldn't still forbid
non-namespaced code in a namespace-using file to avoid confusing weirdness.
--
Larry Garfield AIM: LOLG42
larry@garfieldtech.com ICQ: 6817012
"If nature has made any one thing less susceptible than all others of
exclusive property, it is the action of the thinking power called an idea,
which an individual may exclusively possess as long as he keeps it to
himself; but the moment it is divulged, it forces itself into the possession
of every one, and the receiver cannot dispossess himself of it." -- Thomas
Jefferson
Larry Garfield wrote:
implementation [details] not the concept. I believe that the
implementation needs a little ironing out ... what's the harm in taking
the time to do this? or at least taking the time to let consensus take
hold?No harm, but we will have multiple namespaces per file figured out
pretty soon, and I don't see any new developments with the braces thing,
so what exactly would we wait for?Actually, as I've said previously IF we switch to multiple namespaces per file
(which I honestly have no strong opinion on), switching to braces at the same
time makes sense. It's much easier to parse visually (by a human) in that
case, and there's no reason I know of why we couldn't still forbid
non-namespaced code in a namespace-using file to avoid confusing weirdness.
I know I just finished praising you just some hours ago, Stas, but I'm
going to have to step in and agree with Larry on this one. It really
doesn't make sense for there to be no braces for namespaces (especially
if you're going to allow multiple per file). A namespace is a logical
grouping of classes/functions and other constructs of this type in PHP
use braces. That is very confusing syntax when compared to other areas
of the language.
Jeremy
Am 06.12.2007 um 04:22 schrieb Jeremy Privett:
I know I just finished praising you just some hours ago, Stas, but
I'm going to have to step in and agree with Larry on this one. It
really doesn't make sense for there to be no braces for namespaces
(especially if you're going to allow multiple per file). A namespace
is a logical grouping of classes/functions and other constructs of
this type in PHP use braces. That is very confusing syntax when
compared to other areas of the language.
+1. If we allow multiple namespaces per file, then braces are an
absolute must for consistency IMO.
David
I don't agree with that. I think multiple namespaces per file would be
fine with the current syntax as this is a feature that would not be
used by that many people and if it's used it's not for development
purposes (who wants to read a class bundle with no comments,
linebreaks etc.?) and therefore the readability/consistency doesn't
matter much.
It's not that I don't like braces but imho its not a necessity to move
to braces just to allow multiple namespaces in a file.
Roman
Am 06.12.2007 um 04:22 schrieb Jeremy Privett:
I know I just finished praising you just some hours ago, Stas, but
I'm going to have to step in and agree with Larry on this one. It
really doesn't make sense for there to be no braces for namespaces
(especially if you're going to allow multiple per file). A
namespace is a logical grouping of classes/functions and other
constructs of this type in PHP use braces. That is very confusing
syntax when compared to other areas of the language.+1. If we allow multiple namespaces per file, then braces are an
absolute must for consistency IMO.David
+1. If we allow multiple namespaces per file, then braces are an
absolute must for consistency IMO.
I do not see any relation between consistency and braces.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
If a namespace can be valid for a portion of code in one file, then it
should be possible to use the same syntax as for all other blocks in
PHP. You wouldn't suggest this:
class Foo;
public function zomg() {}
class Bar;
public function lolz() {}
would you? Not the same thing, but you get the idea.
David
Am 06.12.2007 um 18:13 schrieb Stanislav Malyshev:
+1. If we allow multiple namespaces per file, then braces are an
absolute must for consistency IMO.I do not see any relation between consistency and braces.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
would you? Not the same thing, but you get the idea.
Exactly: not the same thing. Only reason I see to consider allowing
multiple namespaces per file is performance reasons.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
I agree that braces are the way to go. Otherwise it's to easy to lose
track of what namespace you're working with.
If a namespace can be valid for a portion of code in one file, then it
should be possible to use the same syntax as for all other blocks in
PHP. You wouldn't suggest this:class Foo;
public function zomg() {}
class Bar;
public function lolz() {}
would you? Not the same thing, but you get the idea.
David
Am 06.12.2007 um 18:13 schrieb Stanislav Malyshev:
+1. If we allow multiple namespaces per file, then braces are an
absolute must for consistency IMO.I do not see any relation between consistency and braces.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com--
--
Michael McGlothlin
Southwest Plumbing Supply
I agree that braces are the way to go. Otherwise it's to easy to lose
track of what namespace you're working with.
This is simple - you always have one namespace per file.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
I agree that braces are the way to go. Otherwise it's to easy to lose
track of what namespace you're working with.
This is simple - you always have one namespace per file.
Then it's best to not allow multiple namespaces for file. If you're not
going to keep the syntax clean then don't do it. PHP already has the bad
habit for many programmers to write totally unreadable code. It's darn
near as bad as Perl in that area. No reason to make it worse.
--
Michael McGlothlin
Southwest Plumbing Supply
Just a thought... You know the whole thing about bundling into one file
improving performance. People do this when they have upwards of 20 classes
being included per request. I bet that most of the time these classes are a
part of a framework / something that would be a part of common name space
anyway.
The whole "One namespace per file" policy will not stop people from bundling
their classes. It will still allow them to bundle, but they will be
restricted to just one file per namespace.
So given a situation where someone has a library of around 20 classes...
Where they would normally bundle down to one file... They bundle it down to
3 files, one for each namespace... There is hardly going to be much of a
performance difference between 1 and 3 includes.
I guess the point I am saying is that everyone is freaking out about the
possible performance loss - but in reality you can still bundle and get 90%
of the bundling gain.
SCOTT MCNAUGHT
Software Developer
Synergy 8 / +617 3397 5212
scott.mcnaught@synergy8.com
You have a point, however it is not always this simple. Some
applications have classes/functions that are not necessarily gathered in
order by their namespaces. It would be a nightmare to try to organize
and then bundle these functions and classes together dynamically into
different files by namespace.
So far I agree with most of the opinions regarding namespaces on here,
but I do think it would be best to allow multiple namespaces per file.
People say this will be confusing, but namespace declarations are pretty
clear, as in clean code they should be on their own line:
namespace usefulStuff ;
class a {}
function z() {}
Yes it has slight potential for chaotic code, but there are hundreds of
ways to create chaotic code, and this is nowhere near the top of the
list. I believe that the benefits of bundling (huge performance
increases in my case) outweigh the risks.
This may not apply to small projects with 2 or 3 namespaces, we also
have to consider larger ones.
Just a thought... You know the whole thing about bundling into one file
improving performance. People do this when they have upwards of 20 classes
being included per request. I bet that most of the time these classes are a
part of a framework / something that would be a part of common name space
anyway.The whole "One namespace per file" policy will not stop people from bundling
their classes. It will still allow them to bundle, but they will be
restricted to just one file per namespace.So given a situation where someone has a library of around 20 classes...
Where they would normally bundle down to one file... They bundle it down to
3 files, one for each namespace... There is hardly going to be much of a
performance difference between 1 and 3 includes.I guess the point I am saying is that everyone is freaking out about the
possible performance loss - but in reality you can still bundle and get 90%
of the bundling gain.SCOTT MCNAUGHT
Software DeveloperSynergy 8 / +617 3397 5212
scott.mcnaught@synergy8.com
Then it's best to not allow multiple namespaces for file. If you're not
That's what I was telling everybody for about a month now :)
going to keep the syntax clean then don't do it. PHP already has the bad
The syntax is very clean, but you are not supposed to use it.
habit for many programmers to write totally unreadable code. It's darn
PHP doesn't have any such habits, programmers do. As if there existed
any language you can't write bad code in :)
near as bad as Perl in that area. No reason to make it worse.
That's what I was saying. But people here seem to disagree.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
PHP already has the bad habit for many programmers to write totally
unreadable code. It's darn near as bad as Perl in that area. No
reason to make it worse.
And you really think not allowing multiple namespaces in a file will
improve that? I don't think so. These people will continue to write
unreadable code, no matter how many restrictions you put into the
language itself to prevent that. And as a negative side-effect the
others lose more and more flexibility of the language.
Apart from that multiple namespaces in a file always result in less
readable code. I don't see how it would be that much better with braces.
Roman
PHP already has the bad habit for many programmers to write totally
unreadable code. It's darn near as bad as Perl in that area. No
reason to make it worse.
And you really think not allowing multiple namespaces in a file will
improve that? I don't think so. These people will continue to write
unreadable code, no matter how many restrictions you put into the
language itself to prevent that. And as a negative side-effect the
others lose more and more flexibility of the language.
Apart from that multiple namespaces in a file always result in less
readable code. I don't see how it would be that much better with braces.
Giving people rope to hang themselves with isn't really a good idea IMO.
That's the difference in taking over somebody else's code from a Perl
programmer or a Python programmer. You can have nasty Python code but it
takes far more effort than with Perl code. PHP is somewhere in the
middle in that it's inconsistent and has several features that make code
a mess to read but it isn't as crazy about offering a dozen ways to do
everything as Perl is.
e.g. Why do we need multiple forms of the if statement? That's just
messy and leads to bad code. Does it really help anybody program better?
Multiple namespaces in a single file, without braces, would end up being
a nightmare when taking over other people's code. Something that happens
often in the work environment.
--
Michael McGlothlin
Southwest Plumbing Supply
programmer or a Python programmer. You can have nasty Python code but it
takes far more effort than with Perl code. PHP is somewhere in the
I don't think writing bad code takes any special effort in any language.
Writing good code takes effort, and it is the fact with any language -
because achieving conceptual clarity and maintaining discipline that is
required for a good code requires the effort.
Multiple namespaces in a single file, without braces, would end up being
a nightmare when taking over other people's code. Something that happens
You are not supposed to have it in other people's code. Neither in yours :)
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
2007/12/5, Jochem Maas jochem@iamjochem.com:
metrics that support your argument that namespaces will make code more
maintainable, offer better structure and cleaner code.
Metrics aren't needed. I believe the almost 5 decades of OOP languages using
some sort of classes grouping and organization, added together to the
possibility of defining encapsulation at this level, is proof enough that
this feature, as we now call it "namespaces" is good enough for the job. And
if not, at least it'll be sugar coating for those who have sweet tooth.
Stanislav Malyshev skrev:
+1 for putting namespaces on the backburner and taking the time to
get it 100% right ...What's "100% right"? Any proposals (besides braces)?
Actually I did mention an alternative a while ago, and that would be to
learn from ECMAScript 4. This is from John Resigs talks:
import dojo.query;
import jquery.query;
use namespace dojo;
query(“#foo”) // using dojo
use namespace jquery;
query(“div > .foo”) // using jquery
No braces, but one is still able to switch from one namespace to another
within the same file. As a teacher I think this style would make sense
to a newbie. I do not claim that this is the "right" way, though, or
that there is such a thing. But it is an option.
Lars Gunther
2007/12/5, Keryx Web webmaster@keryx.se:
Stanislav Malyshev skrev:
+1 for putting namespaces on the backburner and taking the time to
get it 100% right ...What's "100% right"? Any proposals (besides braces)?
Actually I did mention an alternative a while ago, and that would be to
learn from ECMAScript 4. This is from John Resigs talks:import dojo.query;
import jquery.query;use namespace dojo;
query("#foo") // using dojouse namespace jquery;
query("div > .foo") // using jquery
But ECMAScript 4 namespaces are not even like the namespaces we're
discussing here. In that language there's both packages and namespaces.
Packages define class grouping and namespaces work like visibility
declarations (public/protected/private). In the above example what's
happening behind the scenes is the following:
package dojo {
public namespace dojo;
dojo function query(....) { .... }
}
package jquery {
public namespace jquery;
jquery function query(....) { .... }
}
The use namespace directive in ECMAScript4 means:
"I want to be able to see the constructs marked with the namespace provided"
Which is different to:
"Bring that construct from that scope to my current scope" (import)
The first one affects every name and scope, you'll see everything the
"namespace" has to offer, and "namespaces" exist as an object. the second
one is just, practically speaking, a way to make a shortcut for a larger
name.
This makes sense when you're working with E4X because XML namespaces are
binded to namespaces in code. But take an advice from one that has been
working with an ECMAScript4 compliant language: KEEP AWAY FROM ECMASCRIPT4
NAMESPACES.
+1. Maybe PHP 6, as Sebastian suggested.
David
Am 05.12.2007 um 19:22 schrieb Jochem Maas:
+1 for putting namespaces on the backburner and taking the time to
get it 100% right ...Stanislav Malyshev wrote:
some people like a "misguided" implementation of namespaces. The
idea
of namespaces is to prevent collisions in USER land code, not
turning
internal PHP classes into a pile of goo.Yes, idea of namespaces is not to turn PHP classes into a pile of
goo.
But what's your point?I don't quite understand why allowing multiple namespaces is such a
big issue, however - it won't solve the naming collision issue.I'm sorry, I don't understand what you mean by "multiple
namespaces" -
multiple namespaces per file? I object to allowing it for reasons
having
absolutely nothing to do with naming collisions, as anybody
bothering to
actually read what I wrote would immediately know.this implies that your objections to multiple namespaces per file is
valid
whereas objections to the limitation are invalid.apparently people keep 'flogging this horse to death' because they
are not
convinced by your wisdom with regard to this decision - they may be
idiots (me included)
but they are the majority of your users, so it seems.That's because namespaces are not executable blocks.
Neither are classes.
Your point being?
that therefore your argue that "namespaces are not executable
blocks" doesn't
hold up unless your willing to state the inconsistency is one of
your design goals.<remark type="OT" class="irrelevant"> developers will complain, it's in their blood, nothing anyone will ever produce will change that ... somewhere in the future when all code is created without the intervention of man .. even then there will still be a compiler complaining. </remark>No, but, do you really need to have such long names? And besides
that,Yes. Such names are hard fact of life, I have seen them in many
applications and libraries, and I have heard developers to complain
about it.you have to keep repeating them in every file you'd want to use
them -Once per file, yes. Much better than having to spell out all the long
names every time.Just saying "Yes, they are" is not a very good argument -
actually, it's
not an argument at all.No more and no less than "I wonder if they are useful, let's just
delete
them".actually that is not true - a halfbaked concept is pretty much
garanteed to give you
and the users of your product more headaches than no implementation
at all. and
once the genie is out of the bottle your stuck with it - with all
the BC implications
of having to support functionality people would rather see changed.besides possibly having to type a little less, there seems to be
nothing namespaces would
give us [in it's current form] that we cannot achieve already ...
with the bonus that
users are currently not restricted in the way they organize/rollout
their code, at least
with regard to 'bundling' of files.Actually, it's exactly the opposite, as I avoid naming colissions
(point 1), I don't need to import every class I want to use (point
2),
and can group all my classes together in one file (point 3).Of course, if you don't want to hear about namespaces, nobody can
force
you. However, all of your points (avoiding naming collisions, not
needing to import every class you want to use and ability to group
classes together) is exactly how namespaces work right now. If you
refuse to learn about it, it can't be helped, however that just means
you deny yourself a very useful tool.conversly - when namespace functionality is released, every
developer will be confronted
with any problems they might bring with them, at some stage, because
there will be third
party code out there that uses namespaces (code which for the sake
of argument one would
be required to use under some circumstances).--
--
David Zülke
dz@bitxtender.com
Tel: +49 (0)89 57 08 15 15
bitXtender GbR
Paul-Heyse-Straße 6
80336 München
- What is wrong with simple prefixes in the first place? Both PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.
Although most people on the list seem to be coming at this problem assuming
classes, I want to offer a counter-example that is all functions.
In Drupal, our plugin architecture is based on function naming. When a given
event "omg" occurs, something akin to the following frequently happens (a bit
simplified):
$hook = 'omg';
foreach ($modules_that_are_loaded as $module) {
$function = $module .'_'. $hook;
if (function_exists($function)) {
$return[] = $function();
}
}
return $return;
It's a very powerful mechanism, and quite flexible. The one thing it doesn't
offer is, given a function name, determine what module and hook/event it is
for. That's because we use PHP core coding standards, which say to use
function_name for all functions. So given this function name:
views_do_stuff()
Is that the "do stuff" hook from the "views" module/plugin, or the "stuff"
hook from the "views_do" module? Excellent question, and one that cannot be
reliably solved. (There is a module called "views", but nothing is stopping
anyone from writing a "views_do" module and declaring their own "stuff"
hook.)
That has actually come up recently as a problem, where we had to change the
way a feature was implemented in order to avoid that problem of lack of
introspection. (Ironically, it was when we were trying to implement lazy
loading of a larger number of files to improve performance by reducing the
amount of parsed-but-unused code we have.) We also are more and more coming
across very_long_function_names since the function name must begin with the
name of the module, which, if multi-word, can get quite long.
When I saw the namespaces implementation, I realized that was a good solution
to the problem. Instead of $module .'_'. $hook, use $module .'::'. $hook.
That doesn't use namespaces as an alias or a shortener, but as, genuinely, a
namespace.
That's what's wrong with Long_Name_Prefixes. Aside from being a bitch to type
or read, they don't contain as much introspective metadata as namespaces do.
A registry on php.net to avoid collisions solves the problem for only one
tiny sliver of use cases.
If the problem with the current namespace implementation is that it doesn't go
far enough, then the answer is not to drop it entirely but to finish it.
Even if it's not useful in every use case, there are a lot of use cases where
it is useful.
To the other items raised:
- "use MyDate as DateTime". I believe Greg pointed out the solution here.
When PHP 5.5 is released and adds its own Whatever class, you just do the
following:
namespace me;
use Whatever as LegacyWhatever;
class Whatever{}
It's a one-line change to keep your code working. I think that's acceptable,
especially if we ensure that Whatever not existing in the global namespace
(on 5.4) doesn't cause an error. As Stanislav noted, a complete solution is
impossible. The Global namespace is a namespace, and you can't add things to
a namespace and expect there to never be a collision within that namespace.
Duh. :-)
-
No "use Foo::* as *". I can certainly see where that would be useful, but
the lack of it does not mean that the entire namespace implementation must be
thrown out. It still offers other benefits, even if it's not perfect (see
above), and I don't see where adding * capabilities in a later version would
cause a BC break syntactically, so worst case it's added later. -
namespace keyword vs. {}. I've already said before that I prefer the {}
syntax for consistency with other constructs. I am less bothered by the
one-namespace-per-file rule than some, perhaps because I prefer to only parse
the code I need rather than loading everything. (In my common use case,
Drupal, that's a bigger performance win than vice versa.) I do agree that IF
multiple namespaces are allowed in one file, {} makes a lot more syntactic
sense than just a keyword. That said... is the keyword vs. {} issue worth
deep sixing namespaces completely? If so, um, let's switch to {} (with or
without multiple namespaces per file) and solve the problem? :-)
For whatever the opinion of someone who writes PHP all day and not C is worth,
there it is.
--
Larry Garfield AIM: LOLG42
larry@garfieldtech.com ICQ: 6817012
"If nature has made any one thing less susceptible than all others of
exclusive property, it is the action of the thinking power called an idea,
which an individual may exclusively possess as long as he keeps it to
himself; but the moment it is divulged, it forces itself into the possession
of every one, and the receiver cannot dispossess himself of it." -- Thomas
Jefferson
- What is wrong with simple prefixes in the first place? Both PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.Although most people on the list seem to be coming at this problem assuming
classes, I want to offer a counter-example that is all functions.In Drupal, our plugin architecture is based on function naming. When a given
event "omg" occurs, something akin to the following frequently happens (a bit
simplified):$hook = 'omg';
foreach ($modules_that_are_loaded as $module) {
$function = $module .'_'. $hook;
if (function_exists($function)) {
$return[] = $function();
}
}
return $return;It's a very powerful mechanism, and quite flexible. The one thing it doesn't
offer is, given a function name, determine what module and hook/event it is
for. That's because we use PHP core coding standards, which say to use
function_name for all functions. So given this function name:views_do_stuff()
Is that the "do stuff" hook from the "views" module/plugin, or the "stuff"
hook from the "views_do" module? Excellent question, and one that cannot be
reliably solved. (There is a module called "views", but nothing is stopping
anyone from writing a "views_do" module and declaring their own "stuff"
hook.)
<?php
$hook = 'omg';
foreach ($modules_that_are_loaded as $module)
{
$function = $module .'__'. $hook;
if (function_exists($function))
{
$return[] = $function();
}
}
return $return;
?>
There ye have it!
<?php
list( $module, $hook ) = explode( '__', $function );
?>
Namespace support is for people who didn't name their classes/functions
properly. I'm not for or against it.
Cheers,
Rob.
...........................................................
SwarmBuy.com - http://www.swarmbuy.com
Leveraging the buying power of the masses!
...........................................................
- What is wrong with simple prefixes in the first place? Both PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.Although most people on the list seem to be coming at this problem assuming
classes, I want to offer a counter-example that is all functions.In Drupal, our plugin architecture is based on function naming. When a given
event "omg" occurs, something akin to the following frequently happens (a bit
simplified):$hook = 'omg';
foreach ($modules_that_are_loaded as $module) {
$function = $module .'_'. $hook;
if (function_exists($function)) {
$return[] = $function();
}
}
return $return;It's a very powerful mechanism, and quite flexible. The one thing it doesn't
offer is, given a function name, determine what module and hook/event it is
for. That's because we use PHP core coding standards, which say to use
function_name for all functions. So given this function name:views_do_stuff()
Is that the "do stuff" hook from the "views" module/plugin, or the "stuff"
hook from the "views_do" module? Excellent question, and one that cannot be
reliably solved. (There is a module called "views", but nothing is stopping
anyone from writing a "views_do" module and declaring their own "stuff"
hook.)<?php
$hook = 'omg';
foreach ($modules_that_are_loaded as $module)
{
$function = $module .'__'. $hook;
if (function_exists($function))
{
$return[] = $function();
}
}
return $return;?>
There ye have it!
<?php
list( $module, $hook ) = explode( '__', $function );
?>
Namespace support is for people who didn't name their classes/functions
properly. I'm not for or against it.
To paint namespaces with such a broad brush isn't terribly fair. I
see other languages such as Java/Perl/C++ using packages/namespace foo
in much the same way I see some people wanting to use it here. As a
way to shorten really long class names while reducing conflicts.
This isn't a new feature to programming in general. The problem I see
going on here is the desire by some to make it do everything and
wash the dishes. While noble and probably well intentioned, does
feature X really serve the greater good? It can't solve every problem
and still be something that people want to use.
Php already has a ton of stuff in the global namespace, so I don't
know that namespaces can fix collisions/BC overnight. Once namespaces
have a foothold then people can start looking at how to migrate all
the stuff in the global namespace outwards without causing major
problems. While PHP::Time::DateSpan might seem silly to some, it
seems fairly normal in the other languages I program in (Java, Perl).
I would also be perfectly fine with php core laying claim to Time::*.
Its just a fact of life that the global namespace has a limited amout
of real estate and people can't just go snatching up all the good
names just because they were there first.
I vote for starting small. Add namespaces. Allow people to do basic
use statements. I would even be in favor of multiple namespaces per
file, but would prefer if they were wrapped in {} (it seems more
consistent and easier to mentally parse) otherwise I don't care. From
reading emails today I hope this might be some sort of middle ground
that might prevent completely tossing out this feature.
Having said all of that, you can't stop bad programmers from doing at
least something wrong. Especially not in a language like PHP where
you are given so much freedom to do what you want.
--
-Nathan Gordon
If the database server goes down and there is no code to hear it, does
it really go down?
<esc>:wq<CR
Namespace support is for people who didn't name their classes/functions
properly.
Here's a claim so weird I don't know how to parse it.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Namespace support is for people who didn't name their classes/functions
properly.Here's a claim so weird I don't know how to parse it.
I think you're confusing parsing for grokking. Namespace support is
merely candy coating for naming conventions. Namespaces have the same
collision problems that class naming and function naming have. Only
confined to the name of the namespace itself. This is identical to using
a prefix when naming your classes or functions. The only thing
namespaces bring to the table beyond that, is the ability to shorthand
the class names within the namespace... as I said candy coating. If
everyone had named their classes and functions with appropriate prefixes
then this would be a non-issue. Seriously, how were so many people so
short-sighted to think that only they would ever call a class "Date".
There's only a few million other candidate developers out there with the
similar ideas.
Hope this clears up your confusion, although I doubt you were
particularly confused.
Cheers,
Rob.
...........................................................
SwarmBuy.com - http://www.swarmbuy.com
Leveraging the buying power of the masses!
...........................................................
I think you're confusing parsing for grokking. Namespace support is
merely candy coating for naming conventions. Namespaces have the same
Yes, and PHP is merely a candy coating for shoving electrons around
silicon chips. Makes as much sense. Yes, namespaces deal with naming.
No, namespace in not just a naming convention - it is also the mechanics
allowing to use these conventions consistently and conveniently.
collision problems that class naming and function naming have. Only
Only if you insist on not using the namespaces to solve collision
problems. For the 1001th time - you can not expect to put all names into
global space and have the language by some magic to sort it out and go
both ways. One name can mean only one thing, namespaces or not.
Namespaces just allow you more convenient rules for defining what name
means what thing.
confined to the name of the namespace itself. This is identical to using
a prefix when naming your classes or functions. The only thing
Only if you had auto-prefixing and aliasing with underscore prefixes. If
you had, that would be exactly namespaces with _ as separator. I like ::
better.
namespaces bring to the table beyond that, is the ability to shorthand
the class names within the namespace... as I said candy coating. If
You can say it as many times as you like, it doesn't make it true. It is
the capability that enables one to simplify the code by avoiding
spelling out the full name every time.
everyone had named their classes and functions with appropriate prefixes
then this would be a non-issue. Seriously, how were so many people so
As I said, namespaces is not only names, so it is not true.
Hope this clears up your confusion, although I doubt you were
particularly confused.
I wasn't confused, I was surprised that after all the explanations
people still make such strange claims which have nothing to do with what
namespaces really are.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
collision problems that class naming and function naming have. Only
Only if you insist on not using the namespaces to solve collision
problems. For the 1001th time - you can not expect to put all names into
global space and have the language by some magic to sort it out and go
both ways. One name can mean only one thing, namespaces or not.
Namespaces just allow you more convenient rules for defining what name
means what thing.
I would like to second this notion. There are those who would say
that the global namespace is for the use of PHP itself. I would
disagree heartily, PHP as a language is built to serve the developer
who is using it. They should decide what exists in the global
namespace.
When I write a library I will often create functions/classes/variables
that have no business being used outside my library. So I don't see
the need to make the names longer just so I don't collide with someone
else's internal variables/classes/functions.
This paves the way for doing much more advanced things with packages
and run-time loading of code (which I know some people will think
isn't good).
Of all the namespace talk I've heard, the only part I disagree with is:
use Foo::Bar as OtherBar;
This seems like a maintainability nightmare to me as well as having
well having some possible BC issues long-term. If you don't like
someone's class name that much that you have to alias it then just
make your own wrapper class:
class OtherBar extends Foo::Bar {}
Its not like it is that many more characters to write.
So if we have to wait until PHP 6 to get this right, then so be it. I
just see this as being critical to the future of enterprise/large
scale PHP and don't want to see it die.
--
-Nathan Gordon
If the database server goes down and there is no code to hear it, does
it really go down?
<esc>:wq<CR
I agree, I also see this as critical in large applications. The current
implementation may have some problems, yes, but it's not hurting anyone
who's not using namespaces.
The minor issues around namespaces can be worked out in due time, but I
think it would be a huge mistake to drop the whole idea. Most
programming languages have some type of namespace implementation, there
is obviously some usefulness to it.
My personal opinion:
-
Allow multiple namespaces per file (mostly for bundling). Personally,
in my application, this cuts execution time literally from .18 seconds
to about .04. Microseconds, but with alot of users this would definitely
be beneficial. -
Braces or declarations like the current, it doesn't matter. However I
think it is important to be able to use the same namespace in different
blocks, allowing functions to be declared under the same namespace in
different files. Declarations like it is now seem fine. -
Some type of import X as Y statement might be useful, but would be
very easy to abuse. Some people would import too much and defeat the
entire purpose of namespaces. I don't have much of an opinion on this.
In essence, I believe keeping namespaces is a necessity. The only useful
feature I have seen people talking about is multiple namespaces per
file. I also saw a patch on here for it (only about 5 lines of actual
code changed by the way), I set it up on PHP 5.3 and I've been using it
for about 8 hours of constant development and testing with no problems
whatsoever.
collision problems that class naming and function naming have. Only
Only if you insist on not using the namespaces to solve collision
problems. For the 1001th time - you can not expect to put all names into
global space and have the language by some magic to sort it out and go
both ways. One name can mean only one thing, namespaces or not.
Namespaces just allow you more convenient rules for defining what name
means what thing.I would like to second this notion. There are those who would say
that the global namespace is for the use of PHP itself. I would
disagree heartily, PHP as a language is built to serve the developer
who is using it. They should decide what exists in the global
namespace.When I write a library I will often create functions/classes/variables
that have no business being used outside my library. So I don't see
the need to make the names longer just so I don't collide with someone
else's internal variables/classes/functions.This paves the way for doing much more advanced things with packages
and run-time loading of code (which I know some people will think
isn't good).Of all the namespace talk I've heard, the only part I disagree with is:
use Foo::Bar as OtherBar;
This seems like a maintainability nightmare to me as well as having
well having some possible BC issues long-term. If you don't like
someone's class name that much that you have to alias it then just
make your own wrapper class:class OtherBar extends Foo::Bar {}
Its not like it is that many more characters to write.
So if we have to wait until PHP 6 to get this right, then so be it. I
just see this as being critical to the future of enterprise/large
scale PHP and don't want to see it die.--
-Nathan GordonIf the database server goes down and there is no code to hear it, does
it really go down?
<esc>:wq<CR
Hi Nate,
Only if you insist on not using the namespaces to solve collision
problems. For the 1001th time - you can not expect to put all names into
global space and have the language by some magic to sort it out and go
both ways. One name can mean only one thing, namespaces or not.
Namespaces just allow you more convenient rules for defining what name
means what thing.I would like to second this notion. There are those who would say
that the global namespace is for the use of PHP itself. I would
disagree heartily, PHP as a language is built to serve the developer
who is using it. They should decide what exists in the global
namespace.
I'm firmly in the 'global namespace is for the use of PHP itself' camp. Why?
Because it gives users the choice of totally ignoring namespace support if
they don't want to use it, and because allowing user code to define
classnames and functions in the global space via import/use (as opposed to
by default) has a huge potential for difficult-to-debug misuse. If people
want to be able to alias stuff they should be forced to namespace their
code.
When I write a library I will often create functions/classes/variables
that have no business being used outside my library. So I don't see
the need to make the names longer just so I don't collide with someone
else's internal variables/classes/functions.
Fine, so namespace it.
- Steph
namespaces bring to the table beyond that, is the ability to
shorthand the class names within the namespace... as I said candy
coating.You can say it as many times as you like, it doesn't make it true. It
is the capability that enables one to simplify the code by avoiding
spelling out the full name every time.
Ummm, "avoiding spelling out the full name every time" is the same as
shorthanding the class name (or for more clarity, the fully resolved
class name given the namespaces exist).
And I already do that within my code without namespaces.
everyone had named their classes and functions with appropriate
prefixes then this would be a non-issue. Seriously, how were so many
people soAs I said, namespaces is not only names, so it is not true.
Yes, but the main push for namespaces is to solve the problem of
colliding names.
Hope this clears up your confusion, although I doubt you were
particularly confused.I wasn't confused, I was surprised that after all the explanations
people still make such strange claims which have nothing to do with
what namespaces really are.
And as I said before, I'm not for or against namespaces. I still stand
by the phrase that they are sugar. obviously, given the lengths of
arguments and discussions about them on this list, they don't seem to be
contributing in particular to the KISS principle.
Cheers,
Rob.
...........................................................
SwarmBuy.com - http://www.swarmbuy.com
Leveraging the buying power of the masses!
...........................................................
And I already do that within my code without namespaces.
You can also do anything in code without classes, so what? With classes
it works better, and with namespaces it is yet better.
Yes, but the main push for namespaces is to solve the problem of
colliding names.
You can not solve this problem in a way you present it. It's just
contradictory. The main push for namespaces is to help solving it in the
right way - by avoiding single-space problem.
And as I said before, I'm not for or against namespaces. I still stand
by the phrase that they are sugar. obviously, given the lengths of
Well, OK, so that's your opinion. I disagree with it.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
2007/12/5, Robert Cummings robert@interjinn.com:
Namespace support is for people who didn't name their
classes/functions
properly.Here's a claim so weird I don't know how to parse it.
I think you're confusing parsing for grokking. Namespace support is
merely candy coating for naming conventions. Namespaces have the same
collision problems that class naming and function naming have. Only
confined to the name of the namespace itself. This is identical to using
a prefix when naming your classes or functions. The only thing
namespaces bring to the table beyond that, is the ability to shorthand
the class names within the namespace... as I said candy coating. If
everyone had named their classes and functions with appropriate prefixes
then this would be a non-issue. Seriously, how were so many people so
short-sighted to think that only they would ever call a class "Date".
There's only a few million other candidate developers out there with the
similar ideas.
Sorry to intrude again, but that's not entirely true.
As of now, PHP namespaces may be called just sugar coating for naming
conventions, but, as I see it, they're just a first step towards a more
complete implementation of namespaces, which means more granular control
over class visibility and scope. This much enhances encapsulation on a
broader level, which is a basic need for any proper OOP supporting language.
In other words, without namespaces, we can't even start thinking about
encapsulation at package level, we'll just have all our classes publicly
available everywhere.
Hi Larry,
namespace me;
use Whatever as LegacyWhatever;
class Whatever{}
I'd missed that in the ebb and flow. I guess the bug in my copy was fixed
then, good. It still doesn't make sense to have global import though...?
(I'm probably going to kick myself sooo hard for this in the morning...)
- Steph
I think support for multiple namespaces in one file should definitely be
used. As far as using curly braces vs using the namespace declaration,
it doesn't really matter to me, however it is important that i be able
to use the same namespace twice:
namespace a {
function function1() {
return true ;
}
}
// some other code
namespace a {
function function2() {
return false ;
}
}
- "use MyDate as DateTime". I believe Greg pointed out the solution here.
When PHP 5.5 is released and adds its own Whatever class, you just do the
following:namespace me;
use Whatever as LegacyWhatever;
class Whatever{}It's a one-line change to keep your code working. I think that's acceptable,
It's not acceptable, as you're breaking BC.
For whatever the opinion of someone who writes PHP all day and not C
is worth, there it is.
What makes you think I am different?
regards,
Derick
--
Derick Rethans
http://derickrethans.nl | http://ezcomponents.org | http://xdebug.org
Hi Derick,
I also agree with your arguments - beautifying class names is not
reason enough for
introducing namespaces.
On 04.12.2007 at 23:16 Derick Rethans wrote:
- What is wrong with simple prefixes in the first place? Both PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for
different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.
While experimenting with namespaces to use with the next major version
of
TYPO3, I realized that always using a full class name such as
"T3_MyPackage_MySubPackage_Controller_DefaultController"
has many advantages. Autoloading becomes a lot easier and if the
filename
equals the class name (ie. the full name, not only
"DefaultController.php")
you are never in doubt where a file belongs to or comes from.
Therefore we in the TYPO3 project currently tend to not using namespaces
even if PHP6 had support for them.
robert
WE NEED UNICODE!
http://typo3.org/gimmefive
http://buzz.typo3.org/people/robert-lemke/
Hi Derick,
I also agree with your arguments - beautifying class names is not
reason enough for
introducing namespaces.
On 04.12.2007 at 23:16 Derick Rethans wrote:
- What is wrong with simple prefixes in the first place? Both
PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for
different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.While experimenting with namespaces to use with the next major
version of
TYPO3, I realized that always using a full class name such as"T3_MyPackage_MySubPackage_Controller_DefaultController"
has many advantages. Autoloading becomes a lot easier and if the
filename
equals the class name (ie. the full name, not only
"DefaultController.php")
you are never in doubt where a file belongs to or comes from.Therefore we in the TYPO3 project currently tend to not using
namespaces
even if PHP6 had support for them.
Wow, total Deja Vu.
http://www.phpbuilder.com/lists/php-documentation-list/2001071/0109.php
I, for one, would not enjoy typing out:
"T3_MyPackage_MySubPackage_Controller_DefaultController" any more
often than I absolutely had to. And in a somewhat amusing sense,
the "register_global" vs. "local variable" debates aren't that far
off from "register_class_as_global" vs. "local class namespace"
debates....
Maybe we could all just re-read the email archives from back then,
and save ourselves a lot of arguing?
:)
-Bop
Hi Ronald,
Am 05.12.2007 um 11:08 schrieb Ronald Chmara:
http://www.phpbuilder.com/lists/php-documentation-list/
2001071/0109.phpI, for one, would not enjoy typing out:
"T3_MyPackage_MySubPackage_Controller_DefaultController" any more
often than I absolutely had to.
well, in a way I agree - I don't like typing more than I need either.
However, for me verbose naming
of methods, variables and classes is a very important factor for
readable (and maintainable) code -
but that's probably yet another story.
Especially in a framework context there a lot of options how you can
make things more convenient, with
convention over configuration for example. In the end it might turn
out that a developer doesn't have
to type class names that often anymore and the length of such a name
gets less important.
Finally, another important reason for us to not use namespaces is the
lack of available refactoring tools.
Imagine you want to rename a class "T3_Cool_Fancy_Stuff" to
"T3_Cool_Fancy_Tool". A global search / replace
and renaming the class file will usually do - if you use the full
class name everywhere. However, just trying to
search and replace "Stuff" will probably break your code.
robert
http://typo3.org/gimmefive
http://buzz.typo3.org/people/robert-lemke/
Hi!
Especially in a framework context there a lot of options how you can
make things more convenient, with
convention over configuration for example. In the end it might turn out
that a developer doesn't have
to type class names that often anymore and the length of such a name
gets less important.
And I think typing couldn't be a deciding factor, almost every
IDE/editor provide code competition.
Best Regards,
Felhő
Autoload would work exactly the same with namespaces, just do a
str_replace and replace "::" with "_".
Hi Derick,
I also agree with your arguments - beautifying class names is not
reason enough for
introducing namespaces.On 04.12.2007 at 23:16 Derick Rethans wrote:
- What is wrong with simple prefixes in the first place? Both PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for
different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.While experimenting with namespaces to use with the next major version
of
TYPO3, I realized that always using a full class name such as"T3_MyPackage_MySubPackage_Controller_DefaultController"
has many advantages. Autoloading becomes a lot easier and if the
filename
equals the class name (ie. the full name, not only
"DefaultController.php")
you are never in doubt where a file belongs to or comes from.Therefore we in the TYPO3 project currently tend to not using namespaces
even if PHP6 had support for them.robert
Hi Sam,
Am 05.12.2007 um 14:51 schrieb Sam Barrow:
Autoload would work exactly the same with namespaces, just do a
str_replace and replace "::" with "_".
hmm, and what about this (please correct me if I'm wrong):
<?php
namespace T3::MyPackage::Controller;
class Special extends Default {
}
?>
<?php
namespace T3::OtherPackage::Controller;
class Fancy extends Default {
}
?>
A search & replace of "Default" would replace both,
T3::MyPackage::Controller::Default
and T3::OtherPackage::Controller::Default - but they are not the same.
The only way to refactor this would be by the help of a semantic-aware
tool.
Anyway, I'm not against namespaces but the way they are planned to be
implemented currently I'm not really excited about them either.
robert
http://typo3.org/gimmefive
http://buzz.typo3.org/people/robert-lemke/
Anyway, I'm not against namespaces but the way they are planned to be
implemented currently I'm not really excited about them either.
So you are proposing to improve them how?
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
As a developer and member of the community, the following is my two-cents on
the subject:
- As it is impossible to do "use XXX as NativeClass" we get to the
point where we'd have to namespace new internal native classes
otherwise we might introduce BC breaks....Basically prefixing the classnames... This you can already do just
fine without namespaces.
I agree. If the solution to this is to start adding prefixes to the aliased
names, then namespaces lose part of their purpose.
- You have to import every class yourself. You can currently not do:
use myNamespace::* as *; // or similar syntax
Globbing of this nature, in my humbled opinion, would not be the best idea
because of the high potential of problems. But, in the same respect, with
very large applications, it is much more preferable than to manually include
possibly hundreds of namespaces.
- We keep bickering over using { } or not, multiple namespaces in a
file or not... etc. I understand that people want more flexibility,
but also we need a simple to explain implementation. With the
current implementation I see the following problems here:
- You can't stick multiple namespaces in one file
- Unlike other constructs in PHP that mark executable blocks,
namespaces don't use { }.- The "namespace" keyword at the start of a file is somewhat magic,
because it can only appear as first element in your script.
I think this is a huge issue, if only for consistency with other constructs
of the language. There are already three different ways to write an
if/switch/while/for/etc condition: 1) With braces, 2) Without braces, and 3)
Alternate colon syntax (i.e., if ($blah == true):). Maybe namespaces should
conform to the existing conventions instead of introducing a new one that is
likely to just add yet another layer of confusion.
The same can be argued for the multiple-namspaces-per-file argument. If I
can put more than one class in a single file, then I should be able to put
more than one namespace in a file. Performance gains/losses aside, this is a
coding convention, and maintainability starts with consistency.
- What is wrong with simple prefixes in the first place? Both PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.
The only difference, on the surface, that I see with namespaces vs. standard
prefixing is that namespaces has a new keyword and changes the separator
from an underscore to the double colon. Beyond that, without the other
features, namespaces doesn't sound very interesting as a feature of the
language, so as a developer I wouldn't feel compelled to use it in any
capacity.
With all the above considerations, especially my first point, I still have
not
heard any good reason why namespaces in the current implementation are
actually
useful - or what particular case they solve... so I am wondering, are they
really useful? I come now to the conclusion that they are not, and for
myself
(and most likely my work projects) I would have to decide not to go with
namespaces, but instead stick with the 3 letter prefixing. Something that
I
have totally no problem with, as it is nice and easy.
For what it's worth, I would have to completely agree with Derick on this
issue. It just seems that namespaces could be made to do much more than it
already does.
--
It looked like something resembling white marble, which was
probably what it was: something resembling white marble.
-- Douglas Adams, "The Hitchhikers Guide to the Galaxy"
I agree. If the solution to this is to start adding prefixes to the aliased
names, then namespaces lose part of their purpose.
The solution is not to import everything in global space. If you must,
namespaces as such won't help you avoid collisions. The purpose of
namespaces is NOT (I don't know how to make it more clear - should I
use blinking text, flash graphics and pictures of dancing girls/boys in
bikinis?) - it is NOT to allow you shoving all your library classes
into global space and in some magic way make same names mean different
classes by telepathically reading your mind. The purpose of namespaces
is to make working with long names - necessary to avoid collisions -
easier, by enabling not always use the whole long name but sometimes
only a part of it.
Globbing of this nature, in my humbled opinion, would not be the best idea
because of the high potential of problems. But, in the same respect, with
That's exactly why it was dropped. More precisely, it is one of the
reasons - other being it would break lookup performance and bytecode
caches.
I think this is a huge issue, if only for consistency with other constructs
of the language. There are already three different ways to write an
Guys, really, how many times should we beat this particular dead horse?
The only difference, on the surface, that I see with namespaces vs. standard
prefixing is that namespaces has a new keyword and changes the separator
from an underscore to the double colon. Beyond that, without the other
Well, I think reading the actual docs would help to see more. Besides
that, namespaces allow aliasing of prefixes and automatic prefixing.
For what it's worth, I would have to completely agree with Derick on this
issue. It just seems that namespaces could be made to do much more than it
already does.
Leaving braces aside (please!), what capabilities that were not
discussed before do you need?
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
(I don't know how to make it more clear - should I
use blinking text, flash graphics and pictures of dancing girls/boys in
bikinis?)
Stas, that is immature, rude, and completely uncalled for; fine, you are
frustrated with our questions and arguments. Comments like this creates
frustration on our part with the developers. Friction like this could easily
be avoided with a little more tact and diplomacy. Now, about those pictures
of those dancing girls in bikinis.... (that last part, FYI, was for
brevity).
- it is NOT to allow you shoving all your library classes
into global space and in some magic way make same names mean different
classes by telepathically reading your mind. The purpose of namespaces
is to make working with long names - necessary to avoid collisions -
easier, by enabling not always use the whole long name but sometimes
only a part of it.
I understand this point very well Stas. If I misinterpreted how namespaces
work with names that exist both in the namespace and the global space, then
I sincerely apologize to you and anybody else who got offended by my
misinformation. I, like you, am simply concerned with people misusing this
powerful feature in a way that causes more problems for me as a developer
and maintainer of PHP code.
Globbing of this nature, in my humbled opinion, would not be the best
idea
because of the high potential of problems. But, in the same respect,
withThat's exactly why it was dropped. More precisely, it is one of the
reasons - other being it would break lookup performance and bytecode
caches.
FWIW, I think that was a good decision. :)
I think this is a huge issue, if only for consistency with other
constructs
of the language. There are already three different ways to write anGuys, really, how many times should we beat this particular dead horse?
As many times as it takes. Seriously though, I see a lot of posts here that
have people asking for braces. To be fair, I see equally as many posts
asking to not have them, and then there are the ones that don't care either
way. So really, I don't think this issue is completely dead. But, that is
just my personal opinion. I concede this point as an agreement to disagree.
:)
The only difference, on the surface, that I see with namespaces vs.
standard
prefixing is that namespaces has a new keyword and changes the separator
from an underscore to the double colon. Beyond that, without the otherWell, I think reading the actual docs would help to see more. Besides
that, namespaces allow aliasing of prefixes and automatic prefixing.
You are right. Despite my continued following of this list, I failed to
realize that the PHP docs included information on namespaces.
For what it's worth, I would have to completely agree with Derick on
this
issue. It just seems that namespaces could be made to do much more than
it
already does.Leaving braces aside (please!), what capabilities that were not
discussed before do you need?
I know you don't like to hear this Stas, but braces are pretty important --
at the very least, to me. I also believe that having multiple namespaces in
a single file would be very beneficial for the many various reasons
discussed on this list. Other than that, I truly feel that the addition of
namespaces is a great addition to the language. Please do not construe my
e-mail in a negative tone. That was not my intention at all. I do not have
the attitude of "take it or leave it". I just felt compelled to offer my
feelings on the matter as just another voice from userland. :)
--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
--
It looked like something resembling white marble, which was
probably what it was: something resembling white marble.
-- Douglas Adams, "The Hitchhikers Guide to the Galaxy"
Stas, that is immature, rude, and completely uncalled for; fine, you are
frustrated with our questions and arguments. Comments like this creates
What I'm frustrated with is not questions and arguments, but the same
misconceptions about namespaces repeated over and over after it was
explained multiple times it is just not what namespaces are and how they
are supposed to be used. I value feedback and discussion a lot, however
just repeating misconceptions about namespaces does not add anything to
the discussion. I apologize if it come out too harsh, but I really wish
people (not meaning you or anybody personally here, just in general
about the recent discussions) would take some time to get acquainted
with the subject and ask questions if necessary instead of just
repeating wrong things and basing far-reaching conclusions (like "let's
remove namespaces altogether") on misconceptions.
offended by my misinformation. I, like you, am simply concerned with
people misusing this powerful feature in a way that causes more problems
for me as a developer and maintainer of PHP code.
I am concerned with this too. However I don't see any way to prevent
misuse but education.
care either way. So really, I don't think this issue is completely dead.
There will always be people not satisfied with current solution.
However, not seeing any new arguments, going in circles is just a waste
of time.
You are right. Despite my continued following of this list, I failed to
realize that the PHP docs included information on namespaces.
PHP manual does not have it yet - but PHP sources do have it. And these
topic were also extensively discussed on the list. As for the manual,
it's in works, so if you want to help with it you are welcome.
namespaces in a single file would be very beneficial for the many
various reasons discussed on this list. Other than that, I truly feel
that the addition of namespaces is a great addition to the language.
So there's just two issues you see so far - braces and multiple
namespaces per file. The latter issue is still being discussed, so we
are down to one. I'd say we are in a pretty good shape :)
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
What I'm frustrated with is not questions and arguments, but the same
misconceptions about namespaces repeated over and over after it was
explained multiple times it is just not what namespaces are and how they
are supposed to be used. I value feedback and discussion a lot, however
just repeating misconceptions about namespaces does not add anything to
the discussion. I apologize if it come out too harsh, but I really wish
people (not meaning you or anybody personally here, just in general
about the recent discussions) would take some time to get acquainted
with the subject and ask questions if necessary instead of just
repeating wrong things and basing far-reaching conclusions (like "let's
remove namespaces altogether") on misconceptions.
I understand where you are coming from, I really do. I have dealt with users
most all of my adult career, ranging from telephone support for Adobe, up to
providing forum-based support for my current position as a web developer. I
am just coming from a personal attitude that sometimes it's better to not
say anything at all, then it is to just add fuel to the fires. For the
record, despite whatever the original intention of the first poster was, I
wasn't inline with taking namespaces out. I was just trying to add my
feedback (and apparent confusion) to a discussion about namespaces and what
is important to me as a developer.
I am concerned with this too. However I don't see any way to prevent
misuse but education.
And I, at least, appreciate that. For any project, I would shudder to think
the amount of problems that would happen if developers added/removed to/from
their project without a second thought, just because a user asked to do
something.
There will always be people not satisfied with current solution.
However, not seeing any new arguments, going in circles is just a waste
of time.
I agree and disagree. I agree that as developers, you can't please everybody
all of the time. That is a given. But, what I disagree with is that if there
are enough people (and I do not mean the same exact people) asking for
something, then at the very least, that something should remain on the table
for discussion. Now, I admit that there may be discussions that I've missed
or misunderstood, so I apologize if this conclusion was already reached and
I am just not aware.
PHP manual does not have it yet - but PHP sources do have it. And these
topic were also extensively discussed on the list. As for the manual,
it's in works, so if you want to help with it you are welcome.
Hm. After you made your original reply to me, I went to PHP's website and
found namespaces in the manual:
http://www.php.net/manual/en/language.namespaces.php, hence my reply.
And yes, I would be more than happy to help out in any way that I can with
the development of PHP. :)
--
It looked like something resembling white marble, which was
probably what it was: something resembling white marble.
-- Douglas Adams, "The Hitchhikers Guide to the Galaxy"
Hm. After you made your original reply to me, I went to PHP's website
and found namespaces in the manual:
http://www.php.net/manual/en/language.namespaces.php, hence my reply.
Ah. I didn't see it there last time I checked. All hail to docs team,
great work! Must have missed when it was updated, sorry for that.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Hi Derick,
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.
I have found the solutions to every problem I could find, and to my
surprise, even after crafting a new patch to solve some of them, have
found a way to solve all of the problems within the existing
implementation (with a few tweaks, but nothing major changed) or by
specifying new coding conventions.
Summary:
- 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. - 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. - multiple namespaces per file should be allowed, but strongly
discouraged as a coding practice of last resort for most users. - brackets for namespaces is most necessary for hierarchical namespace
implementations. This is not such an implementation, and as such
brackets do not add clarity but do slow down the implementation. - namespaces provide these benefits that are not available in PHP:
a) short, unqualified descriptive class names can be used without
fear of conflicting with an internal class
b) a clear, uniform coding convention on how to avoid conflicts
between your code and others that will help those who have to maintain
the code of others.
c) a way to alias longer names to increase readability and
maintainability of code. - There are some dangers when using namespaces with autoload, but
simple ways of thwarting those dangers. Also dangerous is trusting
external code that is in the same namespace, as functions can be redefined.
Detailed answers:
Derick Rethans wrote:
<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; > ?>
- As it is impossible to do "use XXX as NativeClass" we get to the
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.
You have to import every class yourself. You can currently not do:
use myNamespace::* as *; // or similar syntax
Actually, ::* would only be deterministic if use performed some kind of
autoloading, it's not a question of runtime versus compile-time - it's
simply not possible to determine which class is intended if more than
one ::* is used unless the answer is determined by code loading, this is
why Java/Python import actually loads code as well as aliasing identifiers.
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;
?>
or the ultra-brief method, requiring 3 extra characters over an
unqualified name:
<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
?>
Even more significant, you can use sub-namespaces with this system, each
namespace does not need to be imported separately:
<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
$d = new a::subnamespace::MyClass; // $d is an object of class
PEAR2::Ultra::Long::Package::Name::subnamespace::MyClass
?>
This is dramatically easier to debug than the equivalent import of ::*
(with an added namespace for dramatic effect):
<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name::;
use Symfony::Something::;
$a = new ExampleClass;
$b = new SecondThing;
$c = new ThirdThing;
$d = new subnamespace::MyClass;
$e = new Controller; // which package is this class from?
?>
Looking at the code, it is impossible to determine which package the
classes come from. Here is the same example with current syntax:
<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
use Symfony::Something as s;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
$d = new a::subnamespace::MyClass;
$e = new s::Controller; // now we know for certain this is from Symfony
?>
We keep bickering over using { } or not, multiple namespaces in a
file or not... etc. I understand that people want more flexibility,
but also we need a simple to explain implementation. With the
current implementation I see the following problems here:
- You can't stick multiple namespaces in one file
- Unlike other constructs in PHP that mark executable blocks,
namespaces don't use { }.- The "namespace" keyword at the start of a file is somewhat magic,
because it can only appear as first element in your script.
I have wrestled with this many times, and the best conclusion I can
reach is that (1) we need the flexibility of multiple namespaces per
file, but that (2) we need to strongly discourage it for the reason
that it is going to make debugging harder. There are two valid use
cases for multiple namespaces per file that I have encountered:
- performance. PHP is slightly slower when executing stuff in multiple
files - GTK2. It's always nice to be able to put a GTK2 app in a single file
and this is an alternative to using a phar archive.
There are two philosophies behind namespaces out there, hierarchical and
non-hierarchical. In hierarchical languages like C++ and C#, nested
namespaces can be defined, and sub-namespaces can be defined using
nested code blocks. Other implementations simply don't do this. The
best description I've seen is from a site on Perl namespaces:
"Isaac Newton is not related to Olivia Newton-John, and Newton::Isaac is
not related to Newton::John::Olivia."
Perl, incidentally, uses the package keyword as a combination of
declaration and alias, in that there is no equivalent to PHP's use.
PHP's implementation is a mixture of these approaches. Because it is
closer to Perl's implementation of package, but contains the import
statement from compiled languages like C++, we have to forge a new path.
Having namespace as the start of the file is good because it enforces a
declaration "take note: this file uses namespaces" that might otherwise
be lost.
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.
- What is wrong with simple prefixes in the first place? Both PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.
The only naming conflicts we've had have been with internal classes thus
far, but there is no coding convention in place. Namespaces would
provide a technical solution to a political problem, something that
carries with it intrinsic risks. Fortunately, other languages have
taken this risk before PHP and not had major problems, so we have a
reasonable expectation of success. The implementations of namespacing
vary so widely, it's kind of impossible to generalize on how they do it,
but difference between prefixing and namespaces can be exemplified by
one construct: use.
<?php
// assume we've loaded code for brevity
$a = Zend_Long_Class_Name::singleton(Zend_Long_Class_Name::CONST);
$b = new PEAR2_Long_Class_Name();
Zend_Long_Class_Name::$var = 2;
?>
<?php
namespace php;
use Zend::Long::Class as a;
use PEAR2::Long::Class as b;
$a = a::Name::singleton(a::Name::CONST);
$b = new b::Name();
a::Name::$var = 2;
?>
Also possible with namespaces is switching out an implementation with a
similar API without search/replace (assuming no dynamic class references
are used)
<?php
// before
namespace php;
use Zend::Thing::Implementation;
$a = new Implementation;
?>
<?php
// after
namespace php;
use PEAR2::Does::Same::Thing as Implementation;
$a = new Implementation;
?>
With all the above considerations, especially my first point, I still have not
heard any good reason why namespaces in the current implementation are actually
useful - or what particular case they solve... so I am wondering, are they
really useful? I come now to the conclusion that they are not, and for myself
(and most likely my work projects) I would have to decide not to go with
namespaces, but instead stick with the 3 letter prefixing. Something that I
have totally no problem with, as it is nice and easy.
-
The ability to guarantee short names can be used without danger of
conflicting with a global name. This is possible inside any namespace
declaration, but not in global scope. -
readability, and therefore maintainability increases as redundant
parts of identifiers are removed by use aliasing. This line:
<?php
return new PEAR2_Pyrus_PackageFile_v2Iterator_File(
new
PEAR2_Pyrus_PackageFile_v2Iterator_FileAttribsFilter(
new PEAR2_Pyrus_PackageFile_v2Iterator_FileContents(
$this->packageInfo['contents'], 'contents',
$this)),
RecursiveIteratorIterator::LEAVES_ONLY);
?>
becomes:
<?php
use PEAR2::Pyrus::PackageFile::v2Iterator as i2;
use ::RecursiveIteratorIterator as ri; // currently not possible in CVS
but I have a patch...
// ...
return new i2::File(
new i2::FileAttribsFilter(
new i2::FileContents(
$this->packageInfo['contents'], 'contents',
$this)),
ri::LEAVES_ONLY);
?>
The argument has been made that namespaces can actually increase code
size because class names are so rarely used. This is not true in my
coding experience. As an example, a single file in PEAR2_Pyrus has 25
uses of the classname PEAR2_Pyrus_PackageFile_Exception. Any class
making use of class constants used by another class will be using the
full classname a lot.
- Ability to use common short names (like File, Exception, Date) as
class names within a namespace increases the logical descriptive
qualities of the code, making it easier to understand without
documentation (self-documenting code). For example, in the classname
PEAR2::Pyrus::Config, the only part that really describes anything
important for the user to know about is "Config", the rest is redundant.
In terms of the danger of using namespaced classes with autoload, the
biggest danger is this code:
<?php
namespace Blah;
$a = new Exception('hi');
?>
In this case, the ::Exception class is instantiated.
<?php
namespace Blah;
use Blah::Exception;
$a = new Exception('hi');
?>
Now we guarantee the correct class is loaded. Although this seemed
onerous to me at first, on reflection, there are very few internal
classes that are likely to be overridden by a package (only 98 exist in
my 5.3 build), probably at most 2 in any given package, so this is not a
huge burden.
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()
. Application authors like blogs that run
plugins must be extremely cautious that plugins from third parties
cannot contain redefinitions of core functions inside the blog's
namespace. Of course, any third-party code is dangerous regardless of
language construct, but this is a subtle vector that could be used and
would not be caught by a code scanner unless consciously coded in to
watch for a "namespace foo;" declaration.
I hope this is helpful - by digging deeply into the source and talking
to lots of devs, I have learned a lot about PHP's namespace
implementation in the past 2 days, and I'm certain we have a much better
implementation than I thought we did 2 days ago, and will be writing up
a "how to namespace" and "how not to namespace" guide based on the
pitfalls I've discovered in this quest as well as contributing to the
documentation when things settle.
Greg
Holy wow. That was fantastic! Not to downplay anything that Stas and the
other developers have done -- because let's face it, they've done a
fantastic job themselves -- you have definitely risen above and beyond the
call of duty and really come up with some very compelling counter-arguments.
This really makes me look forward to using namespaces, and to reading your
guides. Thank you for all of the time and effort you, and those who have
spent time helping you, have put into this feature. :)
Hi Greg,
Thanks for the detailed thoughts.
Guides & examples regarding use-cases will definitely be important for the community. I am sure just this email has already been very helpful to many on this list.
Andi
-----Original Message-----
From: Gregory Beaver [mailto:greg@chiaraquartet.net]
Sent: Thursday, December 06, 2007 5:36 PM
To: Derick Rethans
Cc: PHP Developers Mailing List
Subject: [PHP-DEV] A rebuttal to Re: RFC: Dropping NamespaceHi Derick,
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.I have found the solutions to every problem I could find, and to my
surprise, even after crafting a new patch to solve some of them, have
found a way to solve all of the problems within the existing
implementation (with a few tweaks, but nothing major changed) or by
specifying new coding conventions.Summary:
- 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.- 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.- multiple namespaces per file should be allowed, but strongly
discouraged as a coding practice of last resort for most users.- brackets for namespaces is most necessary for hierarchical namespace
implementations. This is not such an implementation, and as such
brackets do not add clarity but do slow down the implementation.- namespaces provide these benefits that are not available in PHP:
a) short, unqualified descriptive class names can be used without
fear of conflicting with an internal class
b) a clear, uniform coding convention on how to avoid conflicts
between your code and others that will help those who have to maintain
the code of others.
c) a way to alias longer names to increase readability and
maintainability of code.- There are some dangers when using namespaces with autoload, but
simple ways of thwarting those dangers. Also dangerous is trusting
external code that is in the same namespace, as functions can be
redefined.Detailed answers:
Derick Rethans wrote:
<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; > ?>
- As it is impossible to do "use XXX as NativeClass" we get to the
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.
You have to import every class yourself. You can currently not do:
use myNamespace::* as *; // or similar syntax
Actually, ::* would only be deterministic if use performed some kind of
autoloading, it's not a question of runtime versus compile-time - it's
simply not possible to determine which class is intended if more than
one ::* is used unless the answer is determined by code loading, this
is
why Java/Python import actually loads code as well as aliasing
identifiers.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;
?>or the ultra-brief method, requiring 3 extra characters over an
unqualified name:<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
?>Even more significant, you can use sub-namespaces with this system,
each
namespace does not need to be imported separately:<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
$d = new a::subnamespace::MyClass; // $d is an object of class
PEAR2::Ultra::Long::Package::Name::subnamespace::MyClass
?>This is dramatically easier to debug than the equivalent import of ::*
(with an added namespace for dramatic effect):<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name::;
use Symfony::Something::;
$a = new ExampleClass;
$b = new SecondThing;
$c = new ThirdThing;
$d = new subnamespace::MyClass;
$e = new Controller; // which package is this class from?
?>Looking at the code, it is impossible to determine which package the
classes come from. Here is the same example with current syntax:<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
use Symfony::Something as s;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
$d = new a::subnamespace::MyClass;
$e = new s::Controller; // now we know for certain this is from Symfony
?>
We keep bickering over using { } or not, multiple namespaces in a
file or not... etc. I understand that people want more
flexibility,
but also we need a simple to explain implementation. With the
current implementation I see the following problems here:
- You can't stick multiple namespaces in one file
- Unlike other constructs in PHP that mark executable blocks,
namespaces don't use { }.- The "namespace" keyword at the start of a file is somewhat
magic,
because it can only appear as first element in your script.I have wrestled with this many times, and the best conclusion I can
reach is that (1) we need the flexibility of multiple namespaces per
file, but that (2) we need to strongly discourage it for the reason
that it is going to make debugging harder. There are two valid use
cases for multiple namespaces per file that I have encountered:
- performance. PHP is slightly slower when executing stuff in
multiple
files- GTK2. It's always nice to be able to put a GTK2 app in a single
file
and this is an alternative to using a phar archive.There are two philosophies behind namespaces out there, hierarchical
and
non-hierarchical. In hierarchical languages like C++ and C#, nested
namespaces can be defined, and sub-namespaces can be defined using
nested code blocks. Other implementations simply don't do this. The
best description I've seen is from a site on Perl namespaces:"Isaac Newton is not related to Olivia Newton-John, and Newton::Isaac
is
not related to Newton::John::Olivia."Perl, incidentally, uses the package keyword as a combination of
declaration and alias, in that there is no equivalent to PHP's use.PHP's implementation is a mixture of these approaches. Because it is
closer to Perl's implementation of package, but contains the import
statement from compiled languages like C++, we have to forge a new
path.Having namespace as the start of the file is good because it enforces a
declaration "take note: this file uses namespaces" that might otherwise
be lost.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.
- What is wrong with simple prefixes in the first place? Both
PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for
different
'namespaces'. We could optionally create a registry on php.net
for
this to avoid conflicts.The only naming conflicts we've had have been with internal classes
thus
far, but there is no coding convention in place. Namespaces would
provide a technical solution to a political problem, something that
carries with it intrinsic risks. Fortunately, other languages have
taken this risk before PHP and not had major problems, so we have a
reasonable expectation of success. The implementations of namespacing
vary so widely, it's kind of impossible to generalize on how they do
it,
but difference between prefixing and namespaces can be exemplified by
one construct: use.<?php
// assume we've loaded code for brevity
$a = Zend_Long_Class_Name::singleton(Zend_Long_Class_Name::CONST);
$b = new PEAR2_Long_Class_Name();
Zend_Long_Class_Name::$var = 2;
?><?php
namespace php;
use Zend::Long::Class as a;
use PEAR2::Long::Class as b;
$a = a::Name::singleton(a::Name::CONST);
$b = new b::Name();
a::Name::$var = 2;
?>Also possible with namespaces is switching out an implementation with a
similar API without search/replace (assuming no dynamic class
references
are used)<?php
// before
namespace php;
use Zend::Thing::Implementation;
$a = new Implementation;
?><?php
// after
namespace php;
use PEAR2::Does::Same::Thing as Implementation;
$a = new Implementation;
?>With all the above considerations, especially my first point, I still
have not
heard any good reason why namespaces in the current implementation
are actually
useful - or what particular case they solve... so I am wondering, are
they
really useful? I come now to the conclusion that they are not, and
for myself
(and most likely my work projects) I would have to decide not to go
with
namespaces, but instead stick with the 3 letter prefixing. Something
that I
have totally no problem with, as it is nice and easy.
The ability to guarantee short names can be used without danger of
conflicting with a global name. This is possible inside any namespace
declaration, but not in global scope.readability, and therefore maintainability increases as redundant
parts of identifiers are removed by use aliasing. This line:<?php
return new PEAR2_Pyrus_PackageFile_v2Iterator_File(
new
PEAR2_Pyrus_PackageFile_v2Iterator_FileAttribsFilter(
new
PEAR2_Pyrus_PackageFile_v2Iterator_FileContents(
$this->packageInfo['contents'], 'contents',
$this)),
RecursiveIteratorIterator::LEAVES_ONLY);
?>becomes:
<?php
use PEAR2::Pyrus::PackageFile::v2Iterator as i2;
use ::RecursiveIteratorIterator as ri; // currently not possible in CVS
but I have a patch...
// ...return new i2::File( new i2::FileAttribsFilter( new i2::FileContents( $this->packageInfo['contents'], 'contents',
$this)),
ri::LEAVES_ONLY);
?>The argument has been made that namespaces can actually increase code
size because class names are so rarely used. This is not true in my
coding experience. As an example, a single file in PEAR2_Pyrus has 25
uses of the classname PEAR2_Pyrus_PackageFile_Exception. Any class
making use of class constants used by another class will be using the
full classname a lot.
- Ability to use common short names (like File, Exception, Date) as
class names within a namespace increases the logical descriptive
qualities of the code, making it easier to understand without
documentation (self-documenting code). For example, in the classname
PEAR2::Pyrus::Config, the only part that really describes anything
important for the user to know about is "Config", the rest is
redundant.In terms of the danger of using namespaced classes with autoload, the
biggest danger is this code:<?php
namespace Blah;
$a = new Exception('hi');
?>In this case, the ::Exception class is instantiated.
<?php
namespace Blah;
use Blah::Exception;
$a = new Exception('hi');
?>Now we guarantee the correct class is loaded. Although this seemed
onerous to me at first, on reflection, there are very few internal
classes that are likely to be overridden by a package (only 98 exist in
my 5.3 build), probably at most 2 in any given package, so this is not
a
huge burden.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 tostrlen()
. Application authors like blogs that run
plugins must be extremely cautious that plugins from third parties
cannot contain redefinitions of core functions inside the blog's
namespace. Of course, any third-party code is dangerous regardless of
language construct, but this is a subtle vector that could be used and
would not be caught by a code scanner unless consciously coded in to
watch for a "namespace foo;" declaration.I hope this is helpful - by digging deeply into the source and talking
to lots of devs, I have learned a lot about PHP's namespace
implementation in the past 2 days, and I'm certain we have a much
better
implementation than I thought we did 2 days ago, and will be writing up
a "how to namespace" and "how not to namespace" guide based on the
pitfalls I've discovered in this quest as well as contributing to the
documentation when things settle.Greg
Hi Greg,
I'm speechless. All of your points are sound and you've obviously done
your homework, here. I agree with Ken in that you've gone above and
beyond on the research and arguments you've presented here.
Excellent work and a hearty +1 to all of your points.
Jeremy
Gregory Beaver wrote:
Hi Derick,
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.I have found the solutions to every problem I could find, and to my
surprise, even after crafting a new patch to solve some of them, have
found a way to solve all of the problems within the existing
implementation (with a few tweaks, but nothing major changed) or by
specifying new coding conventions.Summary:
- 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.- 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.- multiple namespaces per file should be allowed, but strongly
discouraged as a coding practice of last resort for most users.- brackets for namespaces is most necessary for hierarchical namespace
implementations. This is not such an implementation, and as such
brackets do not add clarity but do slow down the implementation.- namespaces provide these benefits that are not available in PHP:
a) short, unqualified descriptive class names can be used without
fear of conflicting with an internal class
b) a clear, uniform coding convention on how to avoid conflicts
between your code and others that will help those who have to maintain
the code of others.
c) a way to alias longer names to increase readability and
maintainability of code.- There are some dangers when using namespaces with autoload, but
simple ways of thwarting those dangers. Also dangerous is trusting
external code that is in the same namespace, as functions can be redefined.Detailed answers:
Derick Rethans wrote:
<snip>
- As it is impossible to do "use XXX as NativeClass" we get to the
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.
You have to import every class yourself. You can currently not do:
use myNamespace::* as *; // or similar syntax
Actually, ::* would only be deterministic if use performed some kind of
autoloading, it's not a question of runtime versus compile-time - it's
simply not possible to determine which class is intended if more than
one ::* is used unless the answer is determined by code loading, this is
why Java/Python import actually loads code as well as aliasing identifiers.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;
?>or the ultra-brief method, requiring 3 extra characters over an
unqualified name:<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
?>Even more significant, you can use sub-namespaces with this system, each
namespace does not need to be imported separately:<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
$d = new a::subnamespace::MyClass; // $d is an object of class
PEAR2::Ultra::Long::Package::Name::subnamespace::MyClass
?>This is dramatically easier to debug than the equivalent import of ::*
(with an added namespace for dramatic effect):<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name::;
use Symfony::Something::;
$a = new ExampleClass;
$b = new SecondThing;
$c = new ThirdThing;
$d = new subnamespace::MyClass;
$e = new Controller; // which package is this class from?
?>Looking at the code, it is impossible to determine which package the
classes come from. Here is the same example with current syntax:<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
use Symfony::Something as s;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
$d = new a::subnamespace::MyClass;
$e = new s::Controller; // now we know for certain this is from Symfony
?>
We keep bickering over using { } or not, multiple namespaces in a
file or not... etc. I understand that people want more flexibility,
but also we need a simple to explain implementation. With the
current implementation I see the following problems here:
- You can't stick multiple namespaces in one file
- Unlike other constructs in PHP that mark executable blocks,
namespaces don't use { }.- The "namespace" keyword at the start of a file is somewhat magic,
because it can only appear as first element in your script.I have wrestled with this many times, and the best conclusion I can
reach is that (1) we need the flexibility of multiple namespaces per
file, but that (2) we need to strongly discourage it for the reason
that it is going to make debugging harder. There are two valid use
cases for multiple namespaces per file that I have encountered:
- performance. PHP is slightly slower when executing stuff in multiple
files- GTK2. It's always nice to be able to put a GTK2 app in a single file
and this is an alternative to using a phar archive.There are two philosophies behind namespaces out there, hierarchical and
non-hierarchical. In hierarchical languages like C++ and C#, nested
namespaces can be defined, and sub-namespaces can be defined using
nested code blocks. Other implementations simply don't do this. The
best description I've seen is from a site on Perl namespaces:"Isaac Newton is not related to Olivia Newton-John, and Newton::Isaac is
not related to Newton::John::Olivia."Perl, incidentally, uses the package keyword as a combination of
declaration and alias, in that there is no equivalent to PHP's use.PHP's implementation is a mixture of these approaches. Because it is
closer to Perl's implementation of package, but contains the import
statement from compiled languages like C++, we have to forge a new path.Having namespace as the start of the file is good because it enforces a
declaration "take note: this file uses namespaces" that might otherwise
be lost.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.
- What is wrong with simple prefixes in the first place? Both PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.The only naming conflicts we've had have been with internal classes thus
far, but there is no coding convention in place. Namespaces would
provide a technical solution to a political problem, something that
carries with it intrinsic risks. Fortunately, other languages have
taken this risk before PHP and not had major problems, so we have a
reasonable expectation of success. The implementations of namespacing
vary so widely, it's kind of impossible to generalize on how they do it,
but difference between prefixing and namespaces can be exemplified by
one construct: use.<?php
// assume we've loaded code for brevity
$a = Zend_Long_Class_Name::singleton(Zend_Long_Class_Name::CONST);
$b = new PEAR2_Long_Class_Name();
Zend_Long_Class_Name::$var = 2;
?><?php
namespace php;
use Zend::Long::Class as a;
use PEAR2::Long::Class as b;
$a = a::Name::singleton(a::Name::CONST);
$b = new b::Name();
a::Name::$var = 2;
?>Also possible with namespaces is switching out an implementation with a
similar API without search/replace (assuming no dynamic class references
are used)<?php
// before
namespace php;
use Zend::Thing::Implementation;
$a = new Implementation;
?><?php
// after
namespace php;
use PEAR2::Does::Same::Thing as Implementation;
$a = new Implementation;
?>With all the above considerations, especially my first point, I still have not
heard any good reason why namespaces in the current implementation are actually
useful - or what particular case they solve... so I am wondering, are they
really useful? I come now to the conclusion that they are not, and for myself
(and most likely my work projects) I would have to decide not to go with
namespaces, but instead stick with the 3 letter prefixing. Something that I
have totally no problem with, as it is nice and easy.
The ability to guarantee short names can be used without danger of
conflicting with a global name. This is possible inside any namespace
declaration, but not in global scope.readability, and therefore maintainability increases as redundant
parts of identifiers are removed by use aliasing. This line:<?php
return new PEAR2_Pyrus_PackageFile_v2Iterator_File(
new
PEAR2_Pyrus_PackageFile_v2Iterator_FileAttribsFilter(
new PEAR2_Pyrus_PackageFile_v2Iterator_FileContents(
$this->packageInfo['contents'], 'contents',
$this)),
RecursiveIteratorIterator::LEAVES_ONLY);
?>becomes:
<?php
use PEAR2::Pyrus::PackageFile::v2Iterator as i2;
use ::RecursiveIteratorIterator as ri; // currently not possible in CVS
but I have a patch...
// ...return new i2::File( new i2::FileAttribsFilter( new i2::FileContents( $this->packageInfo['contents'], 'contents',
$this)),
ri::LEAVES_ONLY);
?>The argument has been made that namespaces can actually increase code
size because class names are so rarely used. This is not true in my
coding experience. As an example, a single file in PEAR2_Pyrus has 25
uses of the classname PEAR2_Pyrus_PackageFile_Exception. Any class
making use of class constants used by another class will be using the
full classname a lot.
- Ability to use common short names (like File, Exception, Date) as
class names within a namespace increases the logical descriptive
qualities of the code, making it easier to understand without
documentation (self-documenting code). For example, in the classname
PEAR2::Pyrus::Config, the only part that really describes anything
important for the user to know about is "Config", the rest is redundant.In terms of the danger of using namespaced classes with autoload, the
biggest danger is this code:<?php
namespace Blah;
$a = new Exception('hi');
?>In this case, the ::Exception class is instantiated.
<?php
namespace Blah;
use Blah::Exception;
$a = new Exception('hi');
?>Now we guarantee the correct class is loaded. Although this seemed
onerous to me at first, on reflection, there are very few internal
classes that are likely to be overridden by a package (only 98 exist in
my 5.3 build), probably at most 2 in any given package, so this is not a
huge burden.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 tostrlen()
. Application authors like blogs that run
plugins must be extremely cautious that plugins from third parties
cannot contain redefinitions of core functions inside the blog's
namespace. Of course, any third-party code is dangerous regardless of
language construct, but this is a subtle vector that could be used and
would not be caught by a code scanner unless consciously coded in to
watch for a "namespace foo;" declaration.I hope this is helpful - by digging deeply into the source and talking
to lots of devs, I have learned a lot about PHP's namespace
implementation in the past 2 days, and I'm certain we have a much better
implementation than I thought we did 2 days ago, and will be writing up
a "how to namespace" and "how not to namespace" guide based on the
pitfalls I've discovered in this quest as well as contributing to the
documentation when things settle.Greg
- 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.
- namespaces provide these benefits that are not available in PHP:
a) short, unqualified descriptive class names can be used without
fear of conflicting with an internal class
Interesting as I was not aware before that when a namespace is active the import goes into that namespace and not into global scope (clashing with core classes there).
But please consider:
-- Date.php --
<?php
namespace php;
class Date {}
?>
-- test.php --
<?php
namespace php;
require_once('autoload.php'); // assume it would require Date.php when asked to do so
print get_class(new Date()
);
?>
Although this code has been future-proofed by adding the "namespace php", it will break if the core introduces a class named Date (will use the wrong class!). It also breaks without the namespace, and maybe it is a mistake to rely on autload here. But this is a case where using namespaces does not protect you from surprises unless you explicitly import ("use") all the classes you need. But that is not as simple as putting a namespace statement on top of all your files to be save.
If new, future core extensions showed up in a reserved PHP:: namespace, you would be >:-).
-mp.
Matthias Pigulla wrote:
- 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.
- namespaces provide these benefits that are not available in PHP:
a) short, unqualified descriptive class names can be used without
fear of conflicting with an internal classInteresting as I was not aware before that when a namespace is active
the import goes into that namespace and not into global scope
(clashing with core classes there).But please consider:
-- Date.php -- <?php namespace php; class Date {} ?>
-- test.php -- <?php namespace php; require_once('autoload.php');
// assume it would require Date.php when asked to do so print
get_class(newDate()
); ?>Although this code has been future-proofed by adding the "namespace
php", it will break if the core introduces a class named Date
(will use the wrong class!). It also breaks without the namespace,
and maybe it is a mistake to rely on autload here. But this is a case
where using namespaces does not protect you from surprises unless you
explicitly import ("use") all the classes you need. But that is not
as simple as putting a namespace statement on top of all your files
to be save.If new, future core extensions showed up in a reserved PHP::
namespace, you would be >:-).
Exactly - which is why you should never put classes, functions or
constants in the php namespace. The convention I am proposing is to
only use php for code that uses re-usable components, not
declares them. In this case, your example would be revised as:
<?php
namespace Mylib;
class Date {}
?>
<?php
namespace php;
use Mylib::Date;
include 'autoload.php'; // note - require_once and () just slow things down
$a = new Date()
;
?>
This convention serves two purposes
- library code is always explicitly "use"d
- name conflicts are impossible
The suggestion to make "namespace php;" implicit is very
interesting, but would defeat its purpose, which is to separate
declarations from use.
Another off-list suggestion was to make "use" outside of a namespace
declaration an error, as this is generally a bad idea that can lead to
many "gotchas".
Greg
Von: Gregory Beaver [mailto:greg@chiaraquartet.net]
Exactly - which is why you should never put classes, functions or
constants in the php namespace. The convention I am proposing is
to
only use php for code that uses re-usable components, not
declares them.
Let alone php. If you just put all of your code into namespace Mylib, you're not safe because according to the name resolution rules, internal classes come after imported ones but before trying to find classes in the current namespace.
- library code is always explicitly "use"d
- name conflicts are impossible
- is the crucial one because that puts your classes ahead of the internal ones in the resolution list. That is not only "library code" you explicitly use, but also all code from "your" own namespace. Having to explicitly enumerate all classes you use in your own namespace in every file may be tedious.
So just to get that straight: Having a namespace statement and no "use" (because all you use is from your library) is a discouraged practise?
Thanks!
-mp.
Hi Matthias,
Let alone php. If you just put all of your code into namespace Mylib,
you're not safe because according to the name resolution rules, internal
classes come after imported ones but before trying to find classes in the
current namespace.
I'd missed that :-( and from what I gather, there's no way to safely change
it either.
OK, apologies for the noise.
- Steph
Matthias Pigulla wrote:
Von: Gregory Beaver [mailto:greg@chiaraquartet.net]
Exactly - which is why you should never put classes, functions or
constants in the php namespace. The convention I am proposing
is to only use php for code that uses re-usable components,
not declares them.Let alone php. If you just put all of your code into namespace
Mylib, you're not safe because according to the name resolution
rules, internal classes come after imported ones but before trying to
find classes in the current namespace.
Right, but as long as you know this, it is not so bad for two reasons,
see below. Even if you don't know this, the chance of a name
collision is extremely unlikely - the most common collision will be
Exception.
- library code is always explicitly "use"d 2) name conflicts are
impossible
- is the crucial one because that puts your classes ahead of the
internal ones in the resolution list. That is not only "library code"
you explicitly use, but also all code from "your" own namespace.
Having to explicitly enumerate all classes you use in your own
namespace in every file may be tedious.So just to get that straight: Having a namespace statement and no
"use" (because all you use is from your library) is a discouraged
practise?
To be clear - this only affects users who are relying on autoload. In
other words, this code works the same way 100% of the time regardless of
load order:
file1.php:
<?php
namespace foo;
class Exception {}
?>
file2.php:
<?php
namespace foo;
include 'file1.php';
$a = new Exception('hi');
echo get_class($a); // foo::Exception
?>
So, if your code explicitly loads external files using include/require,
you need not worry about this issue.
Library authors who are in fact relying upon autoload do need to
explicitly use the classes they import as unqualified names, but this is
far less onerous than it seems on initial thought.
Let's say you're using 10 classes from your own project. The first
instinct is that you then have to have 10 use lines - what a pain!
However, this is not necessary. Here's a realistic sample from
PEAR2_Pyrus's package.xml validator class,
PEAR2::Pyrus::PackageFile::v2::Validator.
<?php
namespace PEAR2::Pyrus::PackageFile::v2;
use PEAR2::Pyrus::PackageFile as pf;
use PEAR2::Pyrus::PackageFile::Exception as _ex
use PEAR2::Pyrus as me;
class Validator {...} // details removed for brevity :)
?>
With the above use statements, I can access these classes:
PEAR2::Pyrus::PackageFile::v2
PEAR2::Pyrus::Validate
PEAR2::Pyrus::PackageFile::Exception
PEAR2::Pyrus::ChannelRegistry
PEAR2::Pyrus::Installer::Role
PEAR2::Pyrus::Config
PEAR2::Pyrus::Config::Exception
PEAR2::Pyrus::Task
PEAR2::Pyrus::Log
PEAR2::Pyrus::Package::Tar
with these shortcuts:
pf::v2
me::Validate
_ex
me::ChannelRegistry
me::Installer::Role
me::Config
me::Config::Exception
me::Task
me::Log
me::Package::Tar
Note that it would be possible to shorten the longer names like
me::Config::Exception, but these classnames are only used once in the
file. The most commonly used classname is
PEAR2::Pyrus::PackageFile::Exception, and so I would choose that as the
shortest name. When one examines these things from a practical
standpoint, having the 4 extra characters "me::" definitely increases
maintainability, as it makes it obvious that this class is from our
library, and not an internal class.
I do think it would be worth putting future internal classes into the
PHP namespace, and it would be a good idea to reserve that namespace
now. The reservation can always be dropped later if necessary.
Greg
If new, future core extensions showed up in a reserved PHP::
namespace, you would be >:-).Exactly - which is why you should never put classes, functions or
constants in the php namespace. The convention I am proposing is to
only use php for code that uses re-usable components, not
declares them. In this case, your example would be revised as:<?php
namespace Mylib;
class Date {}
?><?php
namespace php;
use Mylib::Date;
include 'autoload.php'; // note - require_once and () just slow things down
$a = newDate()
;
?>This convention serves two purposes
- library code is always explicitly "use"d
- name conflicts are impossible
The suggestion to make "namespace php;" implicit is very
interesting, but would defeat its purpose, which is to separate
declarations from use.Another off-list suggestion was to make "use" outside of a namespace
declaration an error, as this is generally a bad idea that can lead to
many "gotchas".Greg
Doesn't strict C++ also have a requirement for a global namespace definition?
It has been a very long time since I did any C++, but I seem to recall a
requirement for a "use std" or something like that directive that I never
actually understood. :-)
If there is a "named global namespace" php, then requiring it in order to
import anything makes sense. It's one extra line of code and doesn't break
BC anymore than using the use keyword does.
Another observation, if one takes the position that library code and "running
code" should always be separated, this setup would encourage that "best
practice" but does not absolutely require it. That fits with the "doing
something dumb should be hard, but not impossible" philosophy. :-) That
recommendation would definitely need to be well-documented.
I overall like this concept. Kudos to Greg, as others have said. One
question I would have is what is the performance hit of braces over a
keyword? (Not a challenge; I genuinely don't know what the C implementation
differences would be that would make a difference.)
--
Larry Garfield AIM: LOLG42
larry@garfieldtech.com ICQ: 6817012
"If nature has made any one thing less susceptible than all others of
exclusive property, it is the action of the thinking power called an idea,
which an individual may exclusively possess as long as he keeps it to
himself; but the moment it is divulged, it forces itself into the possession
of every one, and the receiver cannot dispossess himself of it." -- Thomas
Jefferson
In C++, STD was just a normal namespace with some classes and functions
in it, you didn't have to say "use std" unless you wanted to use
functions in the std namespace.
The "php::" namespace could just be a container for all of the functions
and classes that are currently thrown into the global namespace.
I think the name php is too long and inconvenient to be used for a
namespace for all of the built in php functions. I would suggest "php::"
for built in php functions and "ext::<extension>::" for extension
defined functions.
If new, future core extensions showed up in a reserved PHP::
namespace, you would be >:-).Exactly - which is why you should never put classes, functions or
constants in the php namespace. The convention I am proposing is to
only use php for code that uses re-usable components, not
declares them. In this case, your example would be revised as:<?php
namespace Mylib;
class Date {}
?><?php
namespace php;
use Mylib::Date;
include 'autoload.php'; // note - require_once and () just slow things down
$a = newDate()
;
?>This convention serves two purposes
- library code is always explicitly "use"d
- name conflicts are impossible
The suggestion to make "namespace php;" implicit is very
interesting, but would defeat its purpose, which is to separate
declarations from use.Another off-list suggestion was to make "use" outside of a namespace
declaration an error, as this is generally a bad idea that can lead to
many "gotchas".Greg
Doesn't strict C++ also have a requirement for a global namespace definition?
It has been a very long time since I did any C++, but I seem to recall a
requirement for a "use std" or something like that directive that I never
actually understood. :-)If there is a "named global namespace" php, then requiring it in order to
import anything makes sense. It's one extra line of code and doesn't break
BC anymore than using the use keyword does.Another observation, if one takes the position that library code and "running
code" should always be separated, this setup would encourage that "best
practice" but does not absolutely require it. That fits with the "doing
something dumb should be hard, but not impossible" philosophy. :-) That
recommendation would definitely need to be well-documented.I overall like this concept. Kudos to Greg, as others have said. One
question I would have is what is the performance hit of braces over a
keyword? (Not a challenge; I genuinely don't know what the C implementation
differences would be that would make a difference.)--
Larry Garfield AIM: LOLG42
larry@garfieldtech.com ICQ: 6817012"If nature has made any one thing less susceptible than all others of
exclusive property, it is the action of the thinking power called an idea,
which an individual may exclusively possess as long as he keeps it to
himself; but the moment it is divulged, it forces itself into the possession
of every one, and the receiver cannot dispossess himself of it." -- Thomas
Jefferson
Great work!
+1 from me for your proposals, too!
Roman
Hi Derick,
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.I have found the solutions to every problem I could find, and to my
surprise, even after crafting a new patch to solve some of them, have
found a way to solve all of the problems within the existing
implementation (with a few tweaks, but nothing major changed) or by
specifying new coding conventions.Summary:
- 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.- 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.- multiple namespaces per file should be allowed, but strongly
discouraged as a coding practice of last resort for most users.- brackets for namespaces is most necessary for hierarchical
namespace
implementations. This is not such an implementation, and as such
brackets do not add clarity but do slow down the implementation.- namespaces provide these benefits that are not available in PHP:
a) short, unqualified descriptive class names can be used without
fear of conflicting with an internal class
b) a clear, uniform coding convention on how to avoid conflicts
between your code and others that will help those who have to maintain
the code of others.
c) a way to alias longer names to increase readability and
maintainability of code.- There are some dangers when using namespaces with autoload, but
simple ways of thwarting those dangers. Also dangerous is trusting
external code that is in the same namespace, as functions can be
redefined.Detailed answers:
Derick Rethans wrote:
<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; > ?>
- As it is impossible to do "use XXX as NativeClass" we get to the
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.
You have to import every class yourself. You can currently not do:
use myNamespace::* as *; // or similar syntax
Actually, ::* would only be deterministic if use performed some kind
of
autoloading, it's not a question of runtime versus compile-time - it's
simply not possible to determine which class is intended if more than
one ::* is used unless the answer is determined by code loading,
this is
why Java/Python import actually loads code as well as aliasing
identifiers.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;
?>or the ultra-brief method, requiring 3 extra characters over an
unqualified name:<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
?>Even more significant, you can use sub-namespaces with this system,
each
namespace does not need to be imported separately:<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
$d = new a::subnamespace::MyClass; // $d is an object of class
PEAR2::Ultra::Long::Package::Name::subnamespace::MyClass
?>This is dramatically easier to debug than the equivalent import of ::*
(with an added namespace for dramatic effect):<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name::;
use Symfony::Something::;
$a = new ExampleClass;
$b = new SecondThing;
$c = new ThirdThing;
$d = new subnamespace::MyClass;
$e = new Controller; // which package is this class from?
?>Looking at the code, it is impossible to determine which package the
classes come from. Here is the same example with current syntax:<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
use Symfony::Something as s;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
$d = new a::subnamespace::MyClass;
$e = new s::Controller; // now we know for certain this is from
Symfony
?>
- We keep bickering over using { } or not, multiple namespaces in a
file or not... etc. I understand that people want more flexibility,
but also we need a simple to explain implementation. With the
current implementation I see the following problems here:
- You can't stick multiple namespaces in one file
- Unlike other constructs in PHP that mark executable blocks,
namespaces don't use { }.- The "namespace" keyword at the start of a file is somewhat magic,
because it can only appear as first element in your script.I have wrestled with this many times, and the best conclusion I can
reach is that (1) we need the flexibility of multiple namespaces per
file, but that (2) we need to strongly discourage it for the reason
that it is going to make debugging harder. There are two valid use
cases for multiple namespaces per file that I have encountered:
- performance. PHP is slightly slower when executing stuff in
multiple
files- GTK2. It's always nice to be able to put a GTK2 app in a single
file
and this is an alternative to using a phar archive.There are two philosophies behind namespaces out there, hierarchical
and
non-hierarchical. In hierarchical languages like C++ and C#, nested
namespaces can be defined, and sub-namespaces can be defined using
nested code blocks. Other implementations simply don't do this. The
best description I've seen is from a site on Perl namespaces:"Isaac Newton is not related to Olivia Newton-John, and
Newton::Isaac is
not related to Newton::John::Olivia."Perl, incidentally, uses the package keyword as a combination of
declaration and alias, in that there is no equivalent to PHP's use.PHP's implementation is a mixture of these approaches. Because it is
closer to Perl's implementation of package, but contains the import
statement from compiled languages like C++, we have to forge a new
path.Having namespace as the start of the file is good because it
enforces a
declaration "take note: this file uses namespaces" that might
otherwise
be lost.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.
- What is wrong with simple prefixes in the first place? Both
PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for
different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.The only naming conflicts we've had have been with internal classes
thus
far, but there is no coding convention in place. Namespaces would
provide a technical solution to a political problem, something that
carries with it intrinsic risks. Fortunately, other languages have
taken this risk before PHP and not had major problems, so we have a
reasonable expectation of success. The implementations of namespacing
vary so widely, it's kind of impossible to generalize on how they do
it,
but difference between prefixing and namespaces can be exemplified by
one construct: use.<?php
// assume we've loaded code for brevity
$a = Zend_Long_Class_Name::singleton(Zend_Long_Class_Name::CONST);
$b = new PEAR2_Long_Class_Name();
Zend_Long_Class_Name::$var = 2;
?><?php
namespace php;
use Zend::Long::Class as a;
use PEAR2::Long::Class as b;
$a = a::Name::singleton(a::Name::CONST);
$b = new b::Name();
a::Name::$var = 2;
?>Also possible with namespaces is switching out an implementation
with a
similar API without search/replace (assuming no dynamic class
references
are used)<?php
// before
namespace php;
use Zend::Thing::Implementation;
$a = new Implementation;
?><?php
// after
namespace php;
use PEAR2::Does::Same::Thing as Implementation;
$a = new Implementation;
?>With all the above considerations, especially my first point, I
still have not
heard any good reason why namespaces in the current implementation
are actually
useful - or what particular case they solve... so I am wondering,
are they
really useful? I come now to the conclusion that they are not, and
for myself
(and most likely my work projects) I would have to decide not to go
with
namespaces, but instead stick with the 3 letter prefixing.
Something that I
have totally no problem with, as it is nice and easy.
The ability to guarantee short names can be used without danger of
conflicting with a global name. This is possible inside any namespace
declaration, but not in global scope.readability, and therefore maintainability increases as redundant
parts of identifiers are removed by use aliasing. This line:<?php
return new PEAR2_Pyrus_PackageFile_v2Iterator_File(
new
PEAR2_Pyrus_PackageFile_v2Iterator_FileAttribsFilter(
new
PEAR2_Pyrus_PackageFile_v2Iterator_FileContents(
$this->packageInfo['contents'], 'contents',
$this)),
RecursiveIteratorIterator::LEAVES_ONLY);
?>becomes:
<?php
use PEAR2::Pyrus::PackageFile::v2Iterator as i2;
use ::RecursiveIteratorIterator as ri; // currently not possible in
CVS
but I have a patch...
// ...return new i2::File( new i2::FileAttribsFilter( new i2::FileContents( $this->packageInfo['contents'], 'contents',
$this)),
ri::LEAVES_ONLY);
?>The argument has been made that namespaces can actually increase code
size because class names are so rarely used. This is not true in my
coding experience. As an example, a single file in PEAR2_Pyrus has 25
uses of the classname PEAR2_Pyrus_PackageFile_Exception. Any class
making use of class constants used by another class will be using the
full classname a lot.
- Ability to use common short names (like File, Exception, Date) as
class names within a namespace increases the logical descriptive
qualities of the code, making it easier to understand without
documentation (self-documenting code). For example, in the classname
PEAR2::Pyrus::Config, the only part that really describes anything
important for the user to know about is "Config", the rest is
redundant.In terms of the danger of using namespaced classes with autoload, the
biggest danger is this code:<?php
namespace Blah;
$a = new Exception('hi');
?>In this case, the ::Exception class is instantiated.
<?php
namespace Blah;
use Blah::Exception;
$a = new Exception('hi');
?>Now we guarantee the correct class is loaded. Although this seemed
onerous to me at first, on reflection, there are very few internal
classes that are likely to be overridden by a package (only 98 exist
in
my 5.3 build), probably at most 2 in any given package, so this is
not a
huge burden.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 tostrlen()
. Application authors like blogs that run
plugins must be extremely cautious that plugins from third parties
cannot contain redefinitions of core functions inside the blog's
namespace. Of course, any third-party code is dangerous regardless of
language construct, but this is a subtle vector that could be used and
would not be caught by a code scanner unless consciously coded in to
watch for a "namespace foo;" declaration.I hope this is helpful - by digging deeply into the source and talking
to lots of devs, I have learned a lot about PHP's namespace
implementation in the past 2 days, and I'm certain we have a much
better
implementation than I thought we did 2 days ago, and will be writing
up
a "how to namespace" and "how not to namespace" guide based on the
pitfalls I've discovered in this quest as well as contributing to the
documentation when things settle.Greg
I agree with everything here, especially the solution to multiple
namespaces per file (allow but discourage), but i don't agree with the
php namespace. If any separation of core php and extensions into
namespaces happens, it should be kept as simple as possible, with root
namespaces like "php::" and "ext::". The application should be allowed
to define its own root namespace, or use a namespace such as "app::".
Besides that I think all of your other suggestions are the best ones.
Hi Derick,
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.I have found the solutions to every problem I could find, and to my
surprise, even after crafting a new patch to solve some of them, have
found a way to solve all of the problems within the existing
implementation (with a few tweaks, but nothing major changed) or by
specifying new coding conventions.Summary:
- 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.- 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.- multiple namespaces per file should be allowed, but strongly
discouraged as a coding practice of last resort for most users.- brackets for namespaces is most necessary for hierarchical namespace
implementations. This is not such an implementation, and as such
brackets do not add clarity but do slow down the implementation.- namespaces provide these benefits that are not available in PHP:
a) short, unqualified descriptive class names can be used without
fear of conflicting with an internal class
b) a clear, uniform coding convention on how to avoid conflicts
between your code and others that will help those who have to maintain
the code of others.
c) a way to alias longer names to increase readability and
maintainability of code.- There are some dangers when using namespaces with autoload, but
simple ways of thwarting those dangers. Also dangerous is trusting
external code that is in the same namespace, as functions can be redefined.Detailed answers:
Derick Rethans wrote:
<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; > ?>
- As it is impossible to do "use XXX as NativeClass" we get to the
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.
You have to import every class yourself. You can currently not do:
use myNamespace::* as *; // or similar syntax
Actually, ::* would only be deterministic if use performed some kind of
autoloading, it's not a question of runtime versus compile-time - it's
simply not possible to determine which class is intended if more than
one ::* is used unless the answer is determined by code loading, this is
why Java/Python import actually loads code as well as aliasing identifiers.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;
?>or the ultra-brief method, requiring 3 extra characters over an
unqualified name:<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
?>Even more significant, you can use sub-namespaces with this system, each
namespace does not need to be imported separately:<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
$d = new a::subnamespace::MyClass; // $d is an object of class
PEAR2::Ultra::Long::Package::Name::subnamespace::MyClass
?>This is dramatically easier to debug than the equivalent import of ::*
(with an added namespace for dramatic effect):<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name::;
use Symfony::Something::;
$a = new ExampleClass;
$b = new SecondThing;
$c = new ThirdThing;
$d = new subnamespace::MyClass;
$e = new Controller; // which package is this class from?
?>Looking at the code, it is impossible to determine which package the
classes come from. Here is the same example with current syntax:<?php
namespace php;
use PEAR2::Ultra::Long::Package::Name as a;
use Symfony::Something as s;
$a = new a::ExampleClass;
$b = new a::SecondThing;
$c = new a::ThirdThing;
$d = new a::subnamespace::MyClass;
$e = new s::Controller; // now we know for certain this is from Symfony
?>
We keep bickering over using { } or not, multiple namespaces in a
file or not... etc. I understand that people want more flexibility,
but also we need a simple to explain implementation. With the
current implementation I see the following problems here:
- You can't stick multiple namespaces in one file
- Unlike other constructs in PHP that mark executable blocks,
namespaces don't use { }.- The "namespace" keyword at the start of a file is somewhat magic,
because it can only appear as first element in your script.I have wrestled with this many times, and the best conclusion I can
reach is that (1) we need the flexibility of multiple namespaces per
file, but that (2) we need to strongly discourage it for the reason
that it is going to make debugging harder. There are two valid use
cases for multiple namespaces per file that I have encountered:
- performance. PHP is slightly slower when executing stuff in multiple
files- GTK2. It's always nice to be able to put a GTK2 app in a single file
and this is an alternative to using a phar archive.There are two philosophies behind namespaces out there, hierarchical and
non-hierarchical. In hierarchical languages like C++ and C#, nested
namespaces can be defined, and sub-namespaces can be defined using
nested code blocks. Other implementations simply don't do this. The
best description I've seen is from a site on Perl namespaces:"Isaac Newton is not related to Olivia Newton-John, and Newton::Isaac is
not related to Newton::John::Olivia."Perl, incidentally, uses the package keyword as a combination of
declaration and alias, in that there is no equivalent to PHP's use.PHP's implementation is a mixture of these approaches. Because it is
closer to Perl's implementation of package, but contains the import
statement from compiled languages like C++, we have to forge a new path.Having namespace as the start of the file is good because it enforces a
declaration "take note: this file uses namespaces" that might otherwise
be lost.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.
- What is wrong with simple prefixes in the first place? Both PEAR_,
Zend_, ezc*, and ezp* are perfectly acceptable markers for different
'namespaces'. We could optionally create a registry on php.net for
this to avoid conflicts.The only naming conflicts we've had have been with internal classes thus
far, but there is no coding convention in place. Namespaces would
provide a technical solution to a political problem, something that
carries with it intrinsic risks. Fortunately, other languages have
taken this risk before PHP and not had major problems, so we have a
reasonable expectation of success. The implementations of namespacing
vary so widely, it's kind of impossible to generalize on how they do it,
but difference between prefixing and namespaces can be exemplified by
one construct: use.<?php
// assume we've loaded code for brevity
$a = Zend_Long_Class_Name::singleton(Zend_Long_Class_Name::CONST);
$b = new PEAR2_Long_Class_Name();
Zend_Long_Class_Name::$var = 2;
?><?php
namespace php;
use Zend::Long::Class as a;
use PEAR2::Long::Class as b;
$a = a::Name::singleton(a::Name::CONST);
$b = new b::Name();
a::Name::$var = 2;
?>Also possible with namespaces is switching out an implementation with a
similar API without search/replace (assuming no dynamic class references
are used)<?php
// before
namespace php;
use Zend::Thing::Implementation;
$a = new Implementation;
?><?php
// after
namespace php;
use PEAR2::Does::Same::Thing as Implementation;
$a = new Implementation;
?>With all the above considerations, especially my first point, I still have not
heard any good reason why namespaces in the current implementation are actually
useful - or what particular case they solve... so I am wondering, are they
really useful? I come now to the conclusion that they are not, and for myself
(and most likely my work projects) I would have to decide not to go with
namespaces, but instead stick with the 3 letter prefixing. Something that I
have totally no problem with, as it is nice and easy.
The ability to guarantee short names can be used without danger of
conflicting with a global name. This is possible inside any namespace
declaration, but not in global scope.readability, and therefore maintainability increases as redundant
parts of identifiers are removed by use aliasing. This line:<?php
return new PEAR2_Pyrus_PackageFile_v2Iterator_File(
new
PEAR2_Pyrus_PackageFile_v2Iterator_FileAttribsFilter(
new PEAR2_Pyrus_PackageFile_v2Iterator_FileContents(
$this->packageInfo['contents'], 'contents',
$this)),
RecursiveIteratorIterator::LEAVES_ONLY);
?>becomes:
<?php
use PEAR2::Pyrus::PackageFile::v2Iterator as i2;
use ::RecursiveIteratorIterator as ri; // currently not possible in CVS
but I have a patch...
// ...return new i2::File( new i2::FileAttribsFilter( new i2::FileContents( $this->packageInfo['contents'], 'contents',
$this)),
ri::LEAVES_ONLY);
?>The argument has been made that namespaces can actually increase code
size because class names are so rarely used. This is not true in my
coding experience. As an example, a single file in PEAR2_Pyrus has 25
uses of the classname PEAR2_Pyrus_PackageFile_Exception. Any class
making use of class constants used by another class will be using the
full classname a lot.
- Ability to use common short names (like File, Exception, Date) as
class names within a namespace increases the logical descriptive
qualities of the code, making it easier to understand without
documentation (self-documenting code). For example, in the classname
PEAR2::Pyrus::Config, the only part that really describes anything
important for the user to know about is "Config", the rest is redundant.In terms of the danger of using namespaced classes with autoload, the
biggest danger is this code:<?php
namespace Blah;
$a = new Exception('hi');
?>In this case, the ::Exception class is instantiated.
<?php
namespace Blah;
use Blah::Exception;
$a = new Exception('hi');
?>Now we guarantee the correct class is loaded. Although this seemed
onerous to me at first, on reflection, there are very few internal
classes that are likely to be overridden by a package (only 98 exist in
my 5.3 build), probably at most 2 in any given package, so this is not a
huge burden.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 tostrlen()
. Application authors like blogs that run
plugins must be extremely cautious that plugins from third parties
cannot contain redefinitions of core functions inside the blog's
namespace. Of course, any third-party code is dangerous regardless of
language construct, but this is a subtle vector that could be used and
would not be caught by a code scanner unless consciously coded in to
watch for a "namespace foo;" declaration.I hope this is helpful - by digging deeply into the source and talking
to lots of devs, I have learned a lot about PHP's namespace
implementation in the past 2 days, and I'm certain we have a much better
implementation than I thought we did 2 days ago, and will be writing up
a "how to namespace" and "how not to namespace" guide based on the
pitfalls I've discovered in this quest as well as contributing to the
documentation when things settle.Greg
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.
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.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:
<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; > ?>
- As it is impossible to do "use XXX as NativeClass" we get to the
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.
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 tostrlen()
.
I thought only constants and classes could be parts of namespaces?
regards,
Derick
--
Derick Rethans
http://derickrethans.nl | http://ezcomponents.org | http://xdebug.org
Gregory, this is amazing and makes me - and I think many others - feel
confident, that namespacing will make it into PHP6 in a smooth and very
usable way. Thanks for your inteligent work on that.
I'd be pleased in having namespaces like that.
Regards,
Franziskus
Hi Greg,
- 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.
That answers my main concern, but I'd make it stronger than a
recommendation. I'd make it impossible to import namespaced code into the
global space.
- Steph
Hei,
now some patches by Greg and Dmitry made it into CVS, some of the things
in my mail have been resolved, however, we still need to come up with a
solution to the 1st and most important issue:
- As it is impossible to do "use XXX as NativeClass" we get to the
point where we'd have to namespace new internal native classes
otherwise we might introduce BC breaks. AFAIK, we've always said that
PHP reserves the globals space for it's own use (see also:
http://www.php.net/manual/en/userlandnaming.rules.php). In case we do
add new classes (an example could be DateTimeSpan), they should of
course follow the same format as already existing classes in the
extension (DateTime, DateTimeZone). However introducing the new class
DateTimeSpan might break people's code that do things like:<?php
use myNamespace::DateTimeZone as DateTimeZone;
?>feature versions of people would then show:
Fatal error: Cannot use myNamespace::DateTimeZone as DomDocument
because the name is already in use.It would be silly to require to have to do this:
- Create a class PHP::Date::TimeSpan
- In your scripts:
use PHP::Date::TimeSpanBut with the current implementation, this seems to be the only non-BC
breaking solution. If we chose not to require this silly namespacing
of internal classes, users instead have to do this:<?php
use myNamespace::DateTimeZone as myDateTimeZone;
?>Basically prefixing the classnames... This you can already do just
fine without namespaces.
I know Greg has some ideas with php as recommendation, but I find it
a bit clumsy still. Perhaps Greg can summarize how it will address the
above issue?
regards,
Derick
--
Derick Rethans
http://derickrethans.nl | http://ezcomponents.org | http://xdebug.org
Hi Derick,
Now, you cannot override existing classes with "use" statement.
However inside a namespace you don't have internal classes and "use"
works just fine.
<?php
namespace Foo;
use myNamespace::Bar as stdClass;
?>
I think it is clear decision.
If you like to override internal classes just write your code in your
own namespace.
Allowing class overriding is possible from technical point of view (it
is disabled on purpose), but it'll give more mess than advantage.
Thanks. Dmitry.
Derick Rethans wrote:
Hei,
now some patches by Greg and Dmitry made it into CVS, some of the things
in my mail have been resolved, however, we still need to come up with a
solution to the 1st and most important issue:
- As it is impossible to do "use XXX as NativeClass" we get to the
point where we'd have to namespace new internal native classes
otherwise we might introduce BC breaks. AFAIK, we've always said that
PHP reserves the globals space for it's own use (see also:
http://www.php.net/manual/en/userlandnaming.rules.php). In case we do
add new classes (an example could be DateTimeSpan), they should of
course follow the same format as already existing classes in the
extension (DateTime, DateTimeZone). However introducing the new class
DateTimeSpan might break people's code that do things like:<?php
use myNamespace::DateTimeZone as DateTimeZone;
?>feature versions of people would then show:
Fatal error: Cannot use myNamespace::DateTimeZone as DomDocument
because the name is already in use.It would be silly to require to have to do this:
- Create a class PHP::Date::TimeSpan
- In your scripts:
use PHP::Date::TimeSpanBut with the current implementation, this seems to be the only non-BC
breaking solution. If we chose not to require this silly namespacing
of internal classes, users instead have to do this:<?php
use myNamespace::DateTimeZone as myDateTimeZone;
?>Basically prefixing the classnames... This you can already do just
fine without namespaces.I know Greg has some ideas with php as recommendation, but I find it
a bit clumsy still. Perhaps Greg can summarize how it will address the
above issue?regards,
Derick
Hi again,
I am not sure this will make it through the noise sigh but I'll give a
try :)
Derick Rethans wrote:
Hei,
now some patches by Greg and Dmitry made it into CVS, some of the things
in my mail have been resolved, however, we still need to come up with a
solution to the 1st and most important issue:
- As it is impossible to do "use XXX as NativeClass" we get to the
point where we'd have to namespace new internal native classes
otherwise we might introduce BC breaks. AFAIK, we've always said that
PHP reserves the globals space for it's own use (see also:
http://www.php.net/manual/en/userlandnaming.rules.php). In case we do
add new classes (an example could be DateTimeSpan), they should of
course follow the same format as already existing classes in the
extension (DateTime, DateTimeZone). However introducing the new class
DateTimeSpan might break people's code that do things like:<?php
use myNamespace::DateTimeZone as DateTimeZone;
?>feature versions of people would then show:
Fatal error: Cannot use myNamespace::DateTimeZone as DomDocument
because the name is already in use.It would be silly to require to have to do this:
- Create a class PHP::Date::TimeSpan
- In your scripts:
use PHP::Date::TimeSpanBut with the current implementation, this seems to be the only non-BC
breaking solution. If we chose not to require this silly namespacing
of internal classes, users instead have to do this:<?php
use myNamespace::DateTimeZone as myDateTimeZone;
?>Basically prefixing the classnames... This you can already do just
fine without namespaces.I know Greg has some ideas with php as recommendation, but I find it
a bit clumsy still. Perhaps Greg can summarize how it will address the
above issue?
I've been thinking quite a bit about several suggestions (surprise
surprise). First of all, Marcus Boerger suggested on IRC that "php"
was not the best name, and proposed "user" as a more logical choice
for the convention, which appeals to me more for the obvious reason that
it doesn't have the chance of confusing with "PHP" or "php" should
either of these be adopted by the core folks ever.
I am going to use some shorthand. "internal class is used first" means
this code:
<?php
namespace hithere;
$a = new Exception('hi');
?>
would use ::Exception unles hithere::Exception already exists.
In my inimitable style, for the larger suggestions I've been thinking
about I will list them:
-
having an implicit namespace for unnamespaced code
-
never accessing internal classes inside a namespace (tough to
summarize I explain below) -
allowing override of internal classes with "use" in the global scope
-
keep things the way they work now, and recommend using "namespace
user" for userspace code. -
having an implicit namespace for unnamespaced code
This is an interesting idea that will break autoloaders unless the
implicit namespace is automatically stripped on a call to autoload,
get_class()
and reflection.
Pros:
use myNamespace::DateTimeZone as DateTimeZone; will always work as intended
Cons:
slight performance hit on every autoload caused by a strstr()
check on
classname for "auto::" and same hit on get_class()
, ReflectionClass
stuff
large number of potential "oops" spots for the implicit namespace to
slip into code and break everything horrendously.
the patch would be huge and very dangerous for the above reason until
kinks are worked out.
doesn't solve the "internal class is used first" issue.
- never accessing internal classes inside a namespace
=====================
This basically means changing the autoloading rules to the following
(using the hithere namespace/Exception example from above):
- does hithere::Exception exist?
- if not, autoload it
Pros:
it is not necessary to "use hithere::classname" for every class you
might autoload.
1 hash lookup reduced per autoloaded class (very minor performance gain,
hash lookup is O(1). profiling might not even detect a difference.)
Cons:
to use internal classes, you would need to explicitly use ::Classname;
for each of them.
Code that does not use autoload would also have to explicitly use
::Classname;
code that uses internal classes that wishes to become namespaced would
need to go through and figure out which internal classes are used and
add "use ::Classname" at the top of the file, making porting to
namespaces much more difficult.
- allowing override of internal classes with "use" in the global scope
=====================
This would be surprisingly easy to implement, currently the only thing
preventing it from happening is a 5-10 line check in zend_do_use() to
see if the name requested would conflict with an internal class. Remove
that check and it becomes possible
Pros:
Derick's main issue goes away, name conflicts with internal classes are
never possible when "use"ing them
it becomes possible to change which class is used in a file with 1 line
of code:
<?php
use myNamespace::Exception as Exception;
?>
As opposed to two:
<?php
namespace user;
use myNamespace::Exception as Exception;
?>
Cons:
It is then possible to accidentally override an internal classname used
in the code.
it encourages continuing to declare classes/functions in the global
namespace, resulting in potential name conflicts a la "Date"
Dangit, I wasn't finished when that sent (apparently Ctrl-S sends a
message - I was trying to Ctrl-V to paste)
Gregory Beaver wrote:
Hi again,
I am not sure this will make it through the noise sigh but I'll give a
try :)Derick Rethans wrote:
Hei,
now some patches by Greg and Dmitry made it into CVS, some of the things
in my mail have been resolved, however, we still need to come up with a
solution to the 1st and most important issue:
As it is impossible to do "use XXX as NativeClass" we get to the
point where we'd have to namespace new internal native classes
otherwise we might introduce BC breaks. AFAIK, we've always said that
PHP reserves the globals space for it's own use (see also:
http://www.php.net/manual/en/userlandnaming.rules.php). In case we do
add new classes (an example could be DateTimeSpan), they should of
course follow the same format as already existing classes in the
extension (DateTime, DateTimeZone). However introducing the new class
DateTimeSpan might break people's code that do things like:<?php
use myNamespace::DateTimeZone as DateTimeZone;
?>feature versions of people would then show:
Fatal error: Cannot use myNamespace::DateTimeZone as DomDocument
because the name is already in use.It would be silly to require to have to do this:
- Create a class PHP::Date::TimeSpan
- In your scripts:
use PHP::Date::TimeSpanBut with the current implementation, this seems to be the only non-BC
breaking solution. If we chose not to require this silly namespacing
of internal classes, users instead have to do this:<?php use myNamespace::DateTimeZone as myDateTimeZone; ?>
Basically prefixing the classnames... This you can already do just
fine without namespaces.I know Greg has some ideas with php as recommendation, but I find it
a bit clumsy still. Perhaps Greg can summarize how it will address the
above issue?I've been thinking quite a bit about several suggestions (surprise
surprise). First of all, Marcus Boerger suggested on IRC that "php"
was not the best name, and proposed "user" as a more logical choice
for the convention, which appeals to me more for the obvious reason that
it doesn't have the chance of confusing with "PHP" or "php" should
either of these be adopted by the core folks ever.I am going to use some shorthand. "internal class is used first" means
this code:<?php
namespace hithere;
$a = new Exception('hi');
?>would use ::Exception unles hithere::Exception already exists.
In my inimitable style, for the larger suggestions I've been thinking
about I will list them:
having an implicit namespace for unnamespaced code
never accessing internal classes inside a namespace (tough to
summarize I explain below)allowing override of internal classes with "use" in the global scope
keep things the way they work now, and recommend using "namespace
user" for userspace code.having an implicit namespace for unnamespaced code
=====================This is an interesting idea that will break autoloaders unless the
implicit namespace is automatically stripped on a call to autoload,
get_class()
and reflection.Pros:
use myNamespace::DateTimeZone as DateTimeZone; will always work as intendedCons:
slight performance hit on every autoload caused by astrstr()
check on
classname for "auto::" and same hit onget_class()
, ReflectionClass
stuff
large number of potential "oops" spots for the implicit namespace to
slip into code and break everything horrendously.
the patch would be huge and very dangerous for the above reason until
kinks are worked out.
doesn't solve the "internal class is used first" issue.
- never accessing internal classes inside a namespace
=====================This basically means changing the autoloading rules to the following
(using the hithere namespace/Exception example from above):
- does hithere::Exception exist?
- if not, autoload it
Pros:
it is not necessary to "use hithere::classname" for every class you
might autoload.
1 hash lookup reduced per autoloaded class (very minor performance gain,
hash lookup is O(1). profiling might not even detect a difference.)Cons:
to use internal classes, you would need to explicitly use ::Classname;
for each of them.
Code that does not use autoload would also have to explicitly use
::Classname;
code that uses internal classes that wishes to become namespaced would
need to go through and figure out which internal classes are used and
add "use ::Classname" at the top of the file, making porting to
namespaces much more difficult.
- allowing override of internal classes with "use" in the global scope
=====================This would be surprisingly easy to implement, currently the only thing
preventing it from happening is a 5-10 line check in zend_do_use() to
see if the name requested would conflict with an internal class. Remove
that check and it becomes possiblePros:
Derick's main issue goes away, name conflicts with internal classes are
never possible when "use"ing them
it becomes possible to change which class is used in a file with 1 line
of code:<?php
use myNamespace::Exception as Exception;
?>As opposed to two:
<?php
namespace user;
use myNamespace::Exception as Exception;
?>Cons:
It is then possible to accidentally override an internal classname used
in the code.
it encourages continuing to declare classes/functions in the global
namespace, resulting in potential name conflicts a la "Date"
- keep things the way they work now, and recommend using "namespace
user" for userspace code.
Pros:
explicit declaration of namespace can make code clearer
Cons:
users using global namespace and "use" will get burned.
=========
As a reality check, in the entire lifetime of PHP, there has been only 1
name collision between new PHP classes and pre-existing major
classnames. SplFileInfo was originally a conflict, but that was solved
with a simple prefix to the classname of "Spl." This is an issue, but
until PHP starts adding billions of classes to handle core elements, it
is not a large one. However, it can be easily and simply solved, so I
say why not :).
After enumerating the pros/cons of each point, my personal opinion is
that #1 and #2 are not feasible from either a user or a core developer
standpoint, and would create more problems than they would solve. #3,
however, looks much more appealing than I thought it would. I think
this is a good idea as an addition. I might be inclined to ask for an
E_STRICT
warning that "use My::Exception;" is overriding an internal
class, but that's up to what you all think. Implementing #3 would
remove the con of #4.
To answer Derick's call for clarification on #4, The convention of using
the user namespace for all code that uses namespaced code would
force users to do two things:
- explicitly "use" classnames they wish to shorten by importing them
from another namespace - add "namespace user" to the top of their files.
These two things would mean
- autoload always works as intended
- classes from external projects (dependencies not found in the current
file) are always documented prominently at the top of the file,
increasing maintainability if the project passes on to another developer. - the presence of "namespace user" would also immediately document
the fact that this code is intended to be executed and is not library
code (does not declare classes/functions and only uses them)
Point #1 does not matter to people who don't use autoload, but #2 and #3
both increase the ease of understanding the purpose of code. I've often
had trouble sifting through source code to find the main files that are
executed. If I could have done a simple "grep -e namespace user" it
would make things a lot easier that way.
Thanks,
Greg
Greg,
I've been thinking about this as well and I also concluded that #3 is
the way to go. If I "use" a class with the same name as an internal one,
then I want to reference that class, I don't care about the internal
class, and I don't want an error either. If a new PHP internal class is
added to the future, then having the option of overriding internal class
names guarantees me that my code won't break in an upgrade.
If at the time of writing my code, I know that I am "using" a class with
the same name as an internal one, AND I need to use both, then I can
alias the classes appropriately to avoid clashes, e.g.
Zend/Exception.php
<?php
namespace Zend;
class Exception extends ::Exception
{
// ...
};
?>
test1.php
<?php
use Zend::Exception;
throw new Exception( 'Zend exception occurred' );
?>
test2.php
<?php
use Zend::Exception as ZendException;
if( $someCondition )
throw new ZendException( 'Zend exception occurred' );
else
throw new Exception( 'unknown generic exception' );
?>
Regards,
Jessie
Gregory Beaver wrote:
Dangit, I wasn't finished when that sent (apparently Ctrl-S sends a
message - I was trying to Ctrl-V to paste)Gregory Beaver wrote:
Hi again,
I am not sure this will make it through the noise sigh but I'll give a
try :)Derick Rethans wrote:
Hei,
now some patches by Greg and Dmitry made it into CVS, some of the things
in my mail have been resolved, however, we still need to come up with a
solution to the 1st and most important issue:
As it is impossible to do "use XXX as NativeClass" we get to the
point where we'd have to namespace new internal native classes
otherwise we might introduce BC breaks. AFAIK, we've always said that
PHP reserves the globals space for it's own use (see also:
http://www.php.net/manual/en/userlandnaming.rules.php). In case we do
add new classes (an example could be DateTimeSpan), they should of
course follow the same format as already existing classes in the
extension (DateTime, DateTimeZone). However introducing the new class
DateTimeSpan might break people's code that do things like:<?php
use myNamespace::DateTimeZone as DateTimeZone;
?>feature versions of people would then show:
Fatal error: Cannot use myNamespace::DateTimeZone as DomDocument
because the name is already in use.It would be silly to require to have to do this:
- Create a class PHP::Date::TimeSpan
- In your scripts:
use PHP::Date::TimeSpanBut with the current implementation, this seems to be the only non-BC
breaking solution. If we chose not to require this silly namespacing
of internal classes, users instead have to do this:<?php
use myNamespace::DateTimeZone as myDateTimeZone;
?>Basically prefixing the classnames... This you can already do just
fine without namespaces.I know Greg has some ideas with php as recommendation, but I find it
a bit clumsy still. Perhaps Greg can summarize how it will address the
above issue?I've been thinking quite a bit about several suggestions (surprise
surprise). First of all, Marcus Boerger suggested on IRC that "php"
was not the best name, and proposed "user" as a more logical choice
for the convention, which appeals to me more for the obvious reason that
it doesn't have the chance of confusing with "PHP" or "php" should
either of these be adopted by the core folks ever.I am going to use some shorthand. "internal class is used first" means
this code:<?php
namespace hithere;
$a = new Exception('hi');
?>would use ::Exception unles hithere::Exception already exists.
In my inimitable style, for the larger suggestions I've been thinking
about I will list them:
having an implicit namespace for unnamespaced code
never accessing internal classes inside a namespace (tough to
summarize I explain below)allowing override of internal classes with "use" in the global scope
keep things the way they work now, and recommend using "namespace
user" for userspace code.having an implicit namespace for unnamespaced code
=====================This is an interesting idea that will break autoloaders unless the
implicit namespace is automatically stripped on a call to autoload,
get_class()
and reflection.Pros:
use myNamespace::DateTimeZone as DateTimeZone; will always work as intendedCons:
slight performance hit on every autoload caused by astrstr()
check on
classname for "auto::" and same hit onget_class()
, ReflectionClass
stuff
large number of potential "oops" spots for the implicit namespace to
slip into code and break everything horrendously.
the patch would be huge and very dangerous for the above reason until
kinks are worked out.
doesn't solve the "internal class is used first" issue.
- never accessing internal classes inside a namespace
=====================This basically means changing the autoloading rules to the following
(using the hithere namespace/Exception example from above):
- does hithere::Exception exist?
- if not, autoload it
Pros:
it is not necessary to "use hithere::classname" for every class you
might autoload.
1 hash lookup reduced per autoloaded class (very minor performance gain,
hash lookup is O(1). profiling might not even detect a difference.)Cons:
to use internal classes, you would need to explicitly use ::Classname;
for each of them.
Code that does not use autoload would also have to explicitly use
::Classname;
code that uses internal classes that wishes to become namespaced would
need to go through and figure out which internal classes are used and
add "use ::Classname" at the top of the file, making porting to
namespaces much more difficult.
- allowing override of internal classes with "use" in the global scope
=====================This would be surprisingly easy to implement, currently the only thing
preventing it from happening is a 5-10 line check in zend_do_use() to
see if the name requested would conflict with an internal class. Remove
that check and it becomes possiblePros:
Derick's main issue goes away, name conflicts with internal classes are
never possible when "use"ing them
it becomes possible to change which class is used in a file with 1 line
of code:<?php
use myNamespace::Exception as Exception;
?>As opposed to two:
<?php
namespace user;
use myNamespace::Exception as Exception;
?>Cons:
It is then possible to accidentally override an internal classname used
in the code.
it encourages continuing to declare classes/functions in the global
namespace, resulting in potential name conflicts a la "Date"
- keep things the way they work now, and recommend using "namespace
user" for userspace code.Pros:
explicit declaration of namespace can make code clearerCons:
users using global namespace and "use" will get burned.=========
As a reality check, in the entire lifetime of PHP, there has been only 1
name collision between new PHP classes and pre-existing major
classnames. SplFileInfo was originally a conflict, but that was solved
with a simple prefix to the classname of "Spl." This is an issue, but
until PHP starts adding billions of classes to handle core elements, it
is not a large one. However, it can be easily and simply solved, so I
say why not :).After enumerating the pros/cons of each point, my personal opinion is
that #1 and #2 are not feasible from either a user or a core developer
standpoint, and would create more problems than they would solve. #3,
however, looks much more appealing than I thought it would. I think
this is a good idea as an addition. I might be inclined to ask for an
E_STRICT
warning that "use My::Exception;" is overriding an internal
class, but that's up to what you all think. Implementing #3 would
remove the con of #4.To answer Derick's call for clarification on #4, The convention of using
the user namespace for all code that uses namespaced code would
force users to do two things:
- explicitly "use" classnames they wish to shorten by importing them
from another namespace- add "namespace user" to the top of their files.
These two things would mean
- autoload always works as intended
- classes from external projects (dependencies not found in the current
file) are always documented prominently at the top of the file,
increasing maintainability if the project passes on to another developer.- the presence of "namespace user" would also immediately document
the fact that this code is intended to be executed and is not library
code (does not declare classes/functions and only uses them)Point #1 does not matter to people who don't use autoload, but #2 and #3
both increase the ease of understanding the purpose of code. I've often
had trouble sifting through source code to find the main files that are
executed. If I could have done a simple "grep -e namespace user" it
would make things a lot easier that way.Thanks,
Greg