以下引发错误,指出Exception
无法重新声明。
namespace \NYTD\ReadingListBackend;
class Exception extends \Exception
{
}
但是,删除命名空间声明中的\
前缀不会:
namespace NYTD\ReadingListBackend;
我最近采用了PHP命名空间。我的理解是,以\
为前缀的名称空间代表完全限定名称。
那为什么我不能在命名空间声明中使用前缀?我可以在引用时(例如new \NYTD\ReadingListBackend\Exception
)。如果我在the docs找不到任何内容,我将非常感谢您的完整解释。
答案 0 :(得分:7)
如其他答案所述,namespace
声明始终采用完全限定名称,因此尾随\
将是多余的,不允许使用。
编写namespace \NYTD\ReadingListBackend { ... }
将导致正确的解析错误。
另一方面,当使用分号符号namespace \NYTD\ReadingListBackend;
时,它被解释为namespace\NYTD\ReadingListBackend;
,这是对常量NYTD\ReadingListBackend
的访问(namespace
关键字在此处解析为当前活动的命名空间,在您的情况下是全局命名空间。)
因此,您的代码不会声明任何命名空间(它是全局的),只是尝试访问常量。这就是为什么你最终重新定义Exception
。
顺便说一下,未定义的常量访问不会引发致命错误的原因是类提升。首先评估您的类声明,因此PHP实际上永远不会达到常量访问(即使它首先出现在代码中)。
答案 1 :(得分:2)
那为什么我不能在命名空间声明中使用前缀?
根据定义,当您声明命名空间名称时, 已经完全限定。
但是在命名空间部分代码中,如果需要指定一个完全限定的类名(FQCN),则需要使用前缀来通知PHP class 名称是FQCN。< / p>
令人恼火的是,在您的示例中,PHP在解析时并未出错。我不能告诉你为什么。
namespace \NYTD\ReadingListBackend;
^- this seems wrong but no parse error
然而,PHP使用卷曲符号(一个文件中有多个名称空间)来处理错误:
namespace \NYTD\ReadingListBackend {}
^- parse error in this line
但是对于你的问题,我认为在namespace-name和class-name之间有所区别。
答案 2 :(得分:1)
\
前缀表示'root'或类似的东西。它创建限定名称空间(/Foo/Bar
)的完全限定名称空间(Foo/Bar
)。这仅在使用命名空间时有用,而不是在声明命名空间时。例如:
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)
在声明命名空间时没用,因为你总是从全局('root')命名空间声明一个命名空间:
namespace Foo; // the \Foo namespace
// ...
namespace Bar; // the \Bar namespace, not the \Foo\Bar namespace
// ...
namespace Foo\Bar; // the \Foo\Bar namespace
因为每个名称空间声明都是“完全限定”的,所以PHP不希望在名称空间前面有\
,并且会给你一个错误。