Namespaces – can we keep it simple?

Dmitry Stogov has published the patch on PHP-internals implementing the simple namespace model for PHP that I co-authored. I urge everybody to please take a look and discuss it – best on the internals list since the audience is bigger, but comments here are welcome too.

The main idea of the proposal is to attack one target and this target only – the Super_Long_Really_Annoying_Enormous_Class_Names that lately became the bane of big project developer. All other things are considered secondary to this goal – no attempt to make some different include model, packaging model, etc. This approach, in my opinion, allows to greatly simplify the concept and the mechanics involved. It allows to reduce most of the work to simple text transformation, without any need to create complex hierarchies with obscure rules.

Of course, there are some edge cases still, but we aim to make frequently used cases easy and converting existing code to this model easier, while accepting that some edge cases might be uncomfortable. I am also sure that there are scenarios of which we did not think – and you are welcome to point those out.

One thing I feel might be missing from the current patch is the runtime resolution of namespaced names – currently if you use variable (new $classname) it has to contain the full name, possibly with use of __NAMESPACE__ constant containing current namespace name. I am not sure if we need runtime – it adds some convenience, but requires the engine to do much more work.


21 thoughts on “Namespaces – can we keep it simple?

  1. Anyone tried to apply this patch for php?
    I am aware of the support in 5.3 for namespaces but I need to patch a version prior to 5.3 with namespaces
    support. Thing is I get an error and I am unable to recompile PHP.

  2. Pingback: » Blog Archive » Namespaces FAQ

  3. I highly recommend to implement curly-like namespaces before it would be too late (that is, a lot of php code with per-file namespaces would be out).
    The motivation of the “code not clear” is totally weak in my opinion. Clarity of scripts should be only a responsibility of the coder, any language can be messy if you write it the wrong way, and having curly braces of course doesn’t change anything in this sense, in fact having the possibility to put more than 1 namespace in the same file doesn’t mean you must put 1000 namespace in that file, but you could want to put 3 of them for instance and this doesn’t make the file less clear, but as of now is not possible.
    The only reason I agree with is that the parsing of scripts will be a bit more complicated but as of now I don’t actually think this would ever be a performance issue in respect to all the other time-consuming operations a script must take care of.
    Instead there are a lot of reasons to use curly-brace syntax. First of all, it’s more logical and effective from a syntactic and functional point of view. In fact as of now php was never binded at file level, with which I mean none of the php features required instructions and or directives that limit your action at the file level and introducing them now would be a irreparable and annoying break of the past rules/practices. Beside this there are a lot of other technical reasons. For instance: a lot of shared hosts have some performance issues for excessive file access, with that meaning a lot of disk accesses. So to increase performance of your script is sometimes needed to move all of your code logically separated in more than 1 file to a single-and-bigger file at runtime in some kind of cache system you design. This is of course simple to achieve as of now, just a matter of putting all the php contents in a single file, but if namespaces will be introduced using this syntax this behavior will be broken (and as I said this is against the way php worked so far, with no file binding). There are other reasons but mainly a lot of them (at least the most important) can be summarized in a single vital motivation: flexibility. Why to introduce a syntax that compromises the flexibility of the entire language, if you can avoid that with a little effort?

  4. Pingback: Namespaces no PHP 6

  5. Stas,

    I have started playing around with the PHP6 snaps for windows. I tried the type hinting in a method and got the following error:

    Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM, expecting '&' or T_VARIABLE in *** on line 65

  6. Pingback: Null is Love » Blog Archive » Namespaces Come to PHP

  7. Pingback: Namespaces FAQ « PHP 10.0 Blog

  8. Pingback: weblog » Blog Archive » PHP Namespaces committed

  9. Stas,

    If a nested class is treated like a static property, then its pretty simple, you don’t get the sub-class when instantiating SomeNamespace because SomeClass exists at the class level, not the object level. It’s the same as SomeClass::$some_static now. Likewise, SomeObject would know about other classes within the namespace assuming their scope allows such. Methods and properties within SomeNamespace follow the same rules.

    Spreading things across multiple files is a different issue. The only workable solution I could come up with is introduce an import_class or include_class declaration that would allow you to load a file and have its contents defined as a class. Something like “private include_class ‘/path/to/SomeClass.php’;”. “/path/to/SomeClass.php” would have a traditional declaration of a class. That allows the same class to be used in several different namespaces easily.

    One thing that does skew my point-of-view is that I look at namespaces only in the context of objects. I will give you that classes with sub-classes does force the use of objects on people where procedural code might be more usable. That said, I think it would be nice to have some sort of hierarchy within namespaces instead of treating them solely as prefixes.

  10. Schmalls,

    1. Global one

    2. 🙂

    3. Private classes would be very useful if we had “import *”, but we don’t have such thing. But we’ll think about it.

  11. Stas thanks for the reply.

    1. What happens if you just say Exception? Which one is called (X::Y, Foo::Bar, or Global)?

    2. Sounds good.

    3. If it is too much work, that is fine. I have thought of a few ways to make it happen in userland. Private classes don’t make since without namespaces which is why all classes were accessible before, just like private functions don’t make since without classes. With namespaces available, it should still be considered.

  12. Schmalls, here’s some answers:

    1. Importing two identical names is an error, like class redefinition. You can always use “import as” though. Also note that if you have two namespaces named X::Y and Foo::Bar and both have classes named exception, it’s no problem – you can import X::Y and Foo::Bar and then say Y::Exception and Bar::Exception.

    2. Namespaces is just the notation, so class name Foo::Bar::Baz is the same as class name Foo_Bar_Baz, except for the fact that you can use short form for the former. So it would work with typehints and all other contexts where you use class name. When you use class name dynamically (in a variable) you’d have to use full name however, right now it has no dynamic resolution. Maybe we’ll add it later if we feel the need.

    3. No, no private classes. Since import is a textual operation, it doesn’t really change any symbol tables, just allows you to write shortcuts, and since you could access any class before, you can also access any class now. We thought about private classes but we don’t feel compelling need to do it, and it would definitely complicate the resolution rules.

  13. I don’t like to make it nested classed because it implies all kinds of semantics we don’t want to imply, e.g. – should SomeObject know about other members of SomeNamespace? About functions defined in SomeNamespace? What happens if we instantiate SomeNamespace – do we also get SomeObject? What if I want to add something into namespace or have it for more than one file? Etc.
    Of course we could try and make a model that allows it – and we thought about it – but it would probably much more complicated and we’d like to keep it really simple, so that it would be as obvious as possible how the thing works.

  14. Hey Stas – I’ve emailed Dimtry on this, but I’ll ask you too. Why not allow classes to be declared inside another class as a new type that’s treated like a static?

    class SomeNamespace {
    class SomeObject {
    public function someMethod() { }

    $obj = new SomeNamespace::SomeObject();
    // or

    I’m not sure on the feasibility of such an issue, but it seems like it should be doable.

  15. I love how simple this proposal is, and would really like to see it in the core. I do have a few questions though:

    1. When importing multiple namespaces, what happens when a class of the same name is used in the namespaces? Is an error thrown or does it just select one of the classes on use?

    2. Does type hinting work with the namespaces? (i.e. function doSomething( A::B::C $var ) {})

    3. Is there any way that private classes could be implemented? It seems like it should be easy to check against the __NAMEPSACE__ “constant” to see if access to the private class is allowed or not.

    I would like to have posted this on the internals list, but I”m not signed up and can’t seem to get the newsreader to work correctly.


  16. Pingback: » Community News: Namespaces in PHP6

  17. Main reason why I didn’t go the Ruby way is that it seems that enabling it creates much more complex code. It also makes engine more complex, but that’s secondary. Primary thing is that when you look at the file, you wouldn’t know which namespace you are in.

    I also see no real gain in nesting namespaces – since it’s just text (i.e., unlike Ruby, Foo::Bar::Baz has absolutely no relation to Foo::Bar) why not just write it in full? It’s only written once (that’s the whole purpose 😉 so it shouldn’t be too hard. And different namespaces living in different files would make code more structured (and also easier to autoload).

Comments are closed.