PHP名称空间并在声明中使用\前缀

时间:2012-10-26 15:02:03

标签: php namespaces

以下引发错误,指出Exception无法重新声明。

namespace \NYTD\ReadingListBackend;

class Exception extends \Exception
{
}

但是,删除命名空间声明中的\前缀不会:

namespace NYTD\ReadingListBackend;

我最近采用了PHP命名空间。我的理解是,以\为前缀的名称空间代表完全限定名称

那为什么我不能在命名空间声明中使用前缀?我可以在引用时(例如new \NYTD\ReadingListBackend\Exception)。如果我在the docs找不到任何内容,我将非常感谢您的完整解释。

3 个答案:

答案 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不希望在名称空间前面有\,并且会给你一个错误。