简体   繁体   中英

PHP namespaces and using the \ prefix in declaration

The following throws an error stating Exception can not be redeclared.

namespace \NYTD\ReadingListBackend;

class Exception extends \Exception
{
}

However, removing the \\ prefix in the namespace declaration does not:

namespace NYTD\ReadingListBackend;

I recently adopted PHP namespaces. My understanding is that namespaces prefixed with \\ represent a fully qualified name .

So why can't I use the prefix in the namespace declaration? I can when referencing (eg new \\NYTD\\ReadingListBackend\\Exception ). Would appreciate a full explanation as I couldn't find anything in the docs .

As mentioned in the other answers the namespace declaration always takes a fully-qualified name and as such a trailing \\ would be redundant and is not allowed.

Writing namespace \\NYTD\\ReadingListBackend { ... } will lead to a proper parse error.

When using the semicolon notation namespace \\NYTD\\ReadingListBackend; on the other hand it is interpreted as namespace\\NYTD\\ReadingListBackend; , which is an access to the constant NYTD\\ReadingListBackend (the namespace keyword here resolves to the currently active namespace, which in your case is the global one).

So your code does not declare any namespace (it is global) and just tries to access a constant. That's why you end up redefining Exception .

By the way, the reason why the undefined constant access does not throw a fatal error is class hoisting. Your class declaration is evaluated first, so PHP never actually reaches the constant access (even though it comes first in code).

So why can't I use the prefix in the namespace declaration?

By definition when you declare a namespace name it is already fully qualified.

But inside a namespace'd part of the code, if you need to specify a fully qualified class name (FQCN) you need the prefix to signal PHP that the class name is a FQCN.

What is irritating here is that PHP does not already error out at parse time in your example. I can not tell you why.

namespace \NYTD\ReadingListBackend;
          ^- this seems wrong but no parse error

However PHP does the error with the curly notation (multiple namespaces in one file):

namespace \NYTD\ReadingListBackend {}
                                   ^- parse error in this line

But for your question, I think it's worth to differ between the namespace-name and the class-name.

A \\ prefix means 'root' or something like that. It makes a fully qualified namespace ( /Foo/Bar ) of a qualified namespace ( Foo/Bar ). This is only useful when using namespaces, not when declaring namespaces. For instance:

namespace Foo

class Bar {
    // ...
}

namespace Bar\Baz;

$b = new Bar(); // look for Bar\Baz\Bar()
$b = new Foo\Bar(); // look for Bar\Baz\Foo\Bar()
$b = new \Foo\Bar(); // look for Foo\Bar() (the right one)

It isn't usefull when declaring a namespace, because you always declare a namespace from the global ('root') namespace:

namespace Foo; // the \Foo namespace
// ...
namespace Bar; // the \Bar namespace, not the \Foo\Bar namespace
// ...
namespace Foo\Bar; // the \Foo\Bar namespace

Because every namespace declaration is sort of 'fully qualified' PHP doesn't want a \\ in front of the namespace and gives you an error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM