Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP namespaces and using the \ prefix in declaration

Tags:

namespaces

php

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 (e.g. new \NYTD\ReadingListBackend\Exception). Would appreciate a full explanation as I couldn't find anything in the docs.

like image 699
Jason McCreary Avatar asked Oct 26 '12 15:10

Jason McCreary


People also ask

What is namespace and use in PHP?

Namespaces are qualifiers that solve two different problems: They allow for better organization by grouping classes that work together to perform a task. They allow the same name to be used for more than one class.

What is the difference between namespace and use in PHP?

A namespace is a way of grouping identifiers so that they don't clash. Using a class implies that you can create an instance of that class, not true with namespaces. 2. You can use using-declarations with namespaces, and that's not possible with classes unless you derive from them.

Are namespaces case sensitive PHP?

Note: Namespace names are case-insensitive. Note: The Namespace name PHP , and compound names starting with this name (like PHP\Classes ) are reserved for internal language use and should not be used in the userspace code.

Can we declare multiple namespaces in same file?

Defining multiple namespaces in the same file ¶ Multiple namespaces may also be declared in the same file. There are two allowed syntaxes. This syntax is not recommended for combining namespaces into a single file. Instead it is recommended to use the alternate bracketed syntax.


3 Answers

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).

like image 90
NikiC Avatar answered Nov 15 '22 10:11

NikiC


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.

like image 22
hakre Avatar answered Nov 15 '22 10:11

hakre


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.

like image 26
Wouter J Avatar answered Nov 15 '22 08:11

Wouter J