# Namespace resolution rules has been changed?

- Thread: https://externals.io/message/41837
- Original archive: https://news-web.php.net/php.internals/41837
- Started by David Grudl on 2008-11-10T19:08:08+00:00
- Messages: 13
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #41837 — David Grudl — 2008-11-10T19:08:08+00:00

URL: https://externals.io/message/41837#41837

Hello!

This code leads to fatal error: Class 'Nette\Loaders\Nette\Object'. Is 
it a bug in current implementation or namespace resolution rules has 
been changed?

namespace Nette;

class Object

{}

namespace Nette\Loaders;

class AutoLoader extends Nette\Object

{}

$obj = new AutoLoader;



Thank you,
David Grudl

---

## #41840 — David Grudl — 2008-11-10T22:04:17+00:00

URL: https://externals.io/message/41837#41840

> The problem was that it isn't immediately clear why we would consider
> "Sub\Object" to be the same as "\Sub\Object", but "Object" to be
> different from "\Object" inside a namespace context, but the same
> outside a namespace context.
>   
The "Sub\Object" should be understand as fully qualified identifiers and 
thus considered as the same as "\Sub\Object".

I understand this new behaviour is same as using "relative paths", but 
there is a common best practise to not make dependencies form topper 
namespaces to deeper ones.
So it is rare to have class Company\Software\Base extending 
Company\Software\Web\Forms\Control (i.e. Base extends 
Web\Forms\Control), and it is common have class 
Company\Software\Web\Forms\Control extending Company\Software\Base.

So in real world it means that nearly every usage of "partially 
qualified indentifiers" (Sub\Object) have to be written with preceding 
backslash.

David Grudl

My english is poor but I hope you understand me ;)

---

## #41841 — Stan Vassilev | FM — 2008-11-10T22:11:40+00:00

URL: https://externals.io/message/41837#41841 · In reply to: #41840

> I understand this new behaviour is same as using "relative paths", but 
> there is a common best practise to not make dependencies form topper 
> namespaces to deeper ones.
> So it is rare to have class Company\Software\Base extending 
> Company\Software\Web\Forms\Control (i.e. Base extends Web\Forms\Control), 
> and it is common have class Company\Software\Web\Forms\Control extending 
> Company\Software\Base.
>
> So in real world it means that nearly every usage of "partially qualified 
> indentifiers" (Sub\Object) have to be written with preceding backslash.
>
> David Grudl

Can you please point us to an example describing this best practice?

Aside from this, the problem is: scopes. In other languages we don't have 
preceding separators and those conflicts hence don't exist, since with 
scopes, if a name doesn't exist in the local scope, it's automatically 
bubbled up until it goes right back to the global scope.

In PHP nothing bubbles, hence this doesn't work. We have just one exception 
to this, with global functions in local space which "bubble up" to global 
even without the prefix (which I believe will come to bite us later on).

However there's still one more issue, "use" clauses only understand full 
symbol names, which causes yet another inconsistency:

namespace foo;
use bar\baz as bar_baz;

$a = new bar\baz(); //instantiates class with absolute path "foo\bar\baz"
$b = new bar_baz(); //instantiates class absolute path "bar\baz"

In fact, use doesn't even know what the prefix would mean:

use \bar\baz; // parse error

So it has to be decided which way the system goes to avoid confusion and 
bugs IMO.

Regards, Stan Vassilev

---

## #41846 — David Grudl — 2008-11-10T22:53:55+00:00

URL: https://externals.io/message/41837#41846

> Can you please point us to an example describing this best practice?

For example Namespace Naming Guidelines in .NET 
(http://msdn.microsoft.com/en-us/library/893ke618(VS.71).aspx)

"A nested namespace should have a dependency on types in the containing 
namespace. For example, the classes in the System.Web.UI.Design depend 
on the classes in System.Web.UI. However, the classes in System.Web.UI 
do not depend on the classes in System.Web.UI.Design."

Or Zend Framework source code. There is no class extending class from 
subpackage (class Zend_View extends Zend_View_Abstract is not 
subpackage, viz 
http://framework.zend.com/wiki/display/ZFPROP/Naming+conventions+for+2.0+-+Matthew+Ratzloff).
*
 > *In PHP nothing bubbles, hence this doesn't work. We have just one 
exception to this, with global functions in local space which "bubble 
up" to global even without the prefix (which I believe will come to bite 
us later on).
*
*I understand but I think it doesn't matter. PHP has not qualified 
identifiers yet, so any qualified identifier can be understand as and 
only as fully qualified identifier (ie "absolute path"), like former 
namespace implementation does, and not like "relative path".

David Grudl

---

## #41847 — Stan Vassilev | FM — 2008-11-10T23:00:35+00:00

URL: https://externals.io/message/41837#41847 · In reply to: #41846

> Or Zend Framework source code. There is no class extending class from
> subpackage (class Zend_View extends Zend_View_Abstract is not
> subpackage, viz
> http://framework.zend.com/wiki/display/ZFPROP/Naming+conventions+for+2.0+-+Matthew+Ratzloff).
> *
> > […]
> exception to this, with global functions in local space which "bubble
> up" to global even without the prefix (which I believe will come to bite
> us later on).
> *
> *I understand but I think it doesn't matter. PHP has not qualified
> identifiers yet, so any qualified identifier can be understand as and
> only as fully qualified identifier (ie "absolute path"), like former
> namespace implementation does, and not like "relative path".
>
> David Grudl

The Zend Framework is chock full of classes reaching for inner classes and 
providing them to the world in the form of Adapters, Factories, Drivers, 
etc.

Regards, Stan Vassilev

---

## #41917 — Marcin Kurzyna — 2008-11-14T21:09:32+00:00

URL: https://externals.io/message/41837#41917

Greg Beaver wrote:

> 
> <?php
> namespace foo\classes;
> use sneaky\devil as foo;
> 
> class buh extends foo\stuff {}
> \\ this extends sneaky\devil\stuff. oops... should have used \foo\stuff
> ?>

accualy I have a question about this if i may: why doesn't the use statement 
fall under the same resolution rules as general code? that is why foo isn't
foo\classses\sneaky\devil?

personally i'd find this much more consistent if *anything* below namespace
declaration was relative to it. and i could always use absolute declaration
explicitly if i'd require it:

<?php

namespace foo;

use bar as A;   /// ->resolves as A == \foo\bar
use \bar as B;  /// ->resolves as B == \bar

?>

TIA
m.

---

## #41918 — Gregory Beaver — 2008-11-14T22:58:31+00:00

URL: https://externals.io/message/41837#41918 · In reply to: #41917

Marcin Kurzyna wrote:
> <?php
> 
> namespace foo;
> 
> use bar as A;   /// ->resolves as A == \foo\bar
> use \bar as B;  /// ->resolves as B == \bar
> 
> ?>

Hi Marcin,

Stan also requested this, so it should be considered as a possibility.

Personally, I would rather not introduce this land mine.  It requires
the user to do an implicit prepending of namespace name ("foo") to "bar"
in the use statement as well as a translation of "A", which could fast
lead to unreadable code.

It is probably best to simply require a fully qualified name where it is
intended.  Thus

1) require leading "\" in use statements
2) allow "namespace\blah" in use statements, as this is a valid fully
qualified name.

<?php
namespace my\ns;

// this is a better way to do the suggested "use bar as A;"
use namespace\bar as A;
use \bar as B;

class mine extends \my\parentclass {}
?>

Stas, I'm sure you have an opinion on this?

Greg

---

## #41920 — Stan Vassilev | FM — 2008-11-15T09:45:27+00:00

URL: https://externals.io/message/41837#41920 · In reply to: #41918

> Hi Marcin,
>
> Stan also requested this, so it should be considered as a possibility.
>
> Personally, I would rather not introduce this land mine.  It requires
> the user to do an implicit prepending of namespace name ("foo") to "bar"
> in the use statement as well as a translation of "A", which could fast
> lead to unreadable code.
>
> It is probably best to simply require a fully qualified name where it is
> intended.  Thus
>
> 1) require leading "\" in use statements
> 2) allow "namespace\blah" in use statements, as this is a valid fully
> qualified name.
>
> <?php
> namespace my\ns;
>
> // this is a better way to do the suggested "use bar as A;"
> use namespace\bar as A;
> use \bar as B;
>
> class mine extends \my\parentclass {}
> ?>

Greg, I can't spot where does your example differ from what I and Marcin 
suggested? Please explain.

As for the leading \ for fully qualified identifiers, well it's a necessary 
evil. As you said yourself PHP is PHP, and we have unique constraints to 
meet, we have no scopes, we have no compile time packaging of the resources, 
and since we don't have meta files describing the namespace resources (wink 
wink...), we should stick to a single-rule no-ambiguity system.

For me the only way to make it clear to both humans and parsers alike is the 
filepath semantics, in all places, including use. It's not perfect, there's 
no completely problem-free solution, but "prepend \ for absolute path" is 
able to become muscle memory, while other mixed solutions I've seen are more 
confusing and require more thinking: "wait in this context what was what?".

And there's one more pain point which I posted earlier on the list about, 
but now as I prepare my framework for 5.3 namespaces, I *really* feel the 
pain in practice: the inability to pass a class/function name without 
specifying it fully as a string.

My suggestion was:   use foo\bar\baz as alias;    $name = nameof alias; // 
$name == 'foo\bar\baz'

But this introduces a new keyword: nameof, which could clash with 
function/class/constant "nameof" in existing source code. I could suggest 
simply not having "nameof" and having direct assignment assign the class 
name, but then we clash with constants which have the same name as the 
class. So that's not doable either.

But it's definitely in-your-face issue while using namespaced code.

Regards, Stan Vassilev

---

## #41924 — Gregory Beaver — 2008-11-15T16:26:54+00:00

URL: https://externals.io/message/41837#41924 · In reply to: #41920

Stan Vassilev | FM wrote:
> > […]
> 
> Greg, I can't spot where does your example differ from what I and Marcin
> suggested? Please explain.

I would not allow "use blah\blah as bar;"

> And there's one more pain point which I posted earlier on the list
> about, but now as I prepare my framework for 5.3 namespaces, I *really*
> feel the pain in practice: the inability to pass a class/function name
> without specifying it fully as a string.
> 
> My suggestion was:   use foo\bar\baz as alias;    $name = nameof alias;
> // $name == 'foo\bar\baz'

Are you aware of __NAMESPACE__?  Also, if you are using a lot of
external namespace names, you might consider simply defining constants:

namespace foo\bar\baz;
const ns = __NAMESPACE__;

then you can simply do

use foo\bar\baz;  $name = baz\ns;

I don't see a huge pressing need for nameof since the above is 3 extra
lines of code - total - per NS.

If this sounds good, I will add an example to the new docs
yet-to-be-committed.

Greg

---

## #41926 — Marcin Kurzyna — 2008-11-15T17:07:40+00:00

URL: https://externals.io/message/41837#41926 · In reply to: #41920

"Stan Vassilev | FM" wrote:

> For me the only way to make it clear to both humans and parsers alike is
> the filepath semantics, in all places, including use. It's not perfect,
> there's no completely problem-free solution, but "prepend \ for absolute
> path" is able to become muscle memory, while other mixed solutions I've
> seen are more confusing and require more thinking: "wait in this context
> what was what?".

My point exactly. This was a real pain in the ass while converting from old
to new resolution rules (though I now this is a one-time example).

However i was explaining the new resolution rules to my co-workers recently 
and it was aparent the context dependant resolution isn't clear, while 
understanding: "it's always relative to current namespace" is simple and 
easy. Also most people are familiar with filepath semantics so there is a 
obvious point of reference (and confusion when it's not consistent).


> But this introduces a new keyword: nameof, which could clash with
> function/class/constant "nameof" in existing source code. I could suggest
[...]
> But it's definitely in-your-face issue while using namespaced code.

I'm not shure how big of a problem "nameof" clashing would be, however a way 
to get fully qualified name is a nessesity in my opinion - i strugle with 
this in my framework too. 

Gregs suggestion of __NAMESPACE__ concatenated solution (if i understand it 
correctly) isn't one accualy because __NAMESPACE__ resolves to current 
namespace; and "typeof" might (and probably usually will) be used on aliased 
classes not nessecerely from current namespace.

m.

---

## #41927 — Marcin Kurzyna — 2008-11-15T17:20:09+00:00

URL: https://externals.io/message/41837#41927

David Grudl wrote:

> Why? I have developed framework using PHP namespaces and studied Zend
> Framework source codes and result is: if we use the new resolution rules
> (1), than in nearly all cases developers must prefix class names with \,
> only in few cases prefix is not required. Why? Because usually classes
> in more nested namespaces extends classes in less nested namespaces. If
> you don't believe, look in framework sources :-)
> 
> So, resolution alÃ¡ 1) is nearly in all cases pain and in few cases nice,
> resolution alÃ¡ 2) is nearly in all cases nice and in few cases not too
> nice.

true, however i have a counter example: classes from more general namespace 
that use further nested classes (think some kind of behaviour and different 
drivers/plugins for example).

so while it's true that more nested classes usually extend the less nested 
ones it also common for more generic code to use it's namespace descendants. 
in sutch condition possibility to use just the remaining namespace part is a 
big help and i'd say it's usage would be more comon than single "extends" at 
class definition where you're obligated to supply FQN [1].

> 
> Furthermore, resolution alÃ¡ 1) means, that namespace named foo\stuff is
> fiction - there is only namespace named \foo\stuff. Lets use \foo\stuff
> everywhere:

i second that (at least when FQN is used) - would provide more consistency.

m.


[1] FQN: fully quallified name

---

## #41930 — Stan Vassilev | FM — 2008-11-15T18:59:47+00:00

URL: https://externals.io/message/41837#41930 · In reply to: #41924

> Are you aware of __NAMESPACE__?  Also, if you are using a lot of
> external namespace names, you might consider simply defining constants:
>
> namespace foo\bar\baz;
> const ns = __NAMESPACE__;
>
> then you can simply do
>
> use foo\bar\baz;  $name = baz\ns;
>
> I don't see a huge pressing need for nameof since the above is 3 extra
> lines of code - total - per NS.
>
> If this sounds good, I will add an example to the new docs
> yet-to-be-committed.
>
> Greg

I'm aware of __NAMESPACE__, and your example is kinda creative, but I think 
that's a touch too much acrobatics for something that's a basic need :P 
Consider callbacks, factories, strategies, drivers, adapters, proxies and so 
on which typically may and do pass class/function names around. I don't 
know.

I'd rather endure the pain and write the string in full every single time 
than cause extra confusion in my source code :)

Regards, Stan Vassilev

---

## #41933 — Stan Vassilev | FM — 2008-11-15T19:54:24+00:00

URL: https://externals.io/message/41837#41933

> Why? I have developed framework using PHP namespaces and studied Zend 
> Framework source codes and result is: if we use the new resolution rules 
> (1), than in nearly all cases developers must prefix class names with \, 
> only in few cases prefix is not required. Why? Because usually classes in 
> more nested namespaces extends classes in less nested namespaces. If you 
> don't believe, look in framework sources :-)

A quick study on the Zend Framework source reveals most top-level classes 
requiring, using, and accepting as arguments "more inner" classes and 
interfaces in the relevant namespace:

Zend_Acl ==> Zend_Acl_Resource_Interface, Zend_Acl_Role_Interface, 
Zend_Acl_Role_Registry, Zend_Acl_Assert_Registry...

Zend_Auth ==> Zend_Auth_Storage_Session, Zend_Auth_Storage_Interface, 
Zend_Auth_Adapter_Interface...

Zend_Cache ==> Zend_Cache_Core, Zend_Cache_Frontend, Zend_Cache_Backend 
(including all specific frontend/backend adapters).

Zend_Db ==> it's a factory for all classes like: Zend_Db_Adapter_*

Zend_Pdf ==> Zend_Pdf_Page, Zend_Pdf_Cmap, Zend_Pdf_Font, Zend_Pdf_Style, 
Zend_Pdf_Parser, Zend_Pdf_Trailer, Zend_Pdf_Color etc.

So, I really suggest we leave that argument out.

Regard, Stan Vassilev
