7

下面抛出一个错误,说明Exception不能重新声明。

namespace \NYTD\ReadingListBackend;

class Exception extends \Exception
{
}

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

namespace NYTD\ReadingListBackend;

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

那么为什么我不能在命名空间声明中使用前缀呢?我可以在引用时(例如new \NYTD\ReadingListBackend\Exception)。希望得到完整的解释,因为我在文档中找不到任何内容。

4

3 回答 3

8

如其他答案中所述,namespace声明始终采用完全限定的名称,因此尾随\将是多余的并且是不允许的。

写入namespace \NYTD\ReadingListBackend { ... }会导致正确的解析错误。

namespace \NYTD\ReadingListBackend;另一方面,当使用分号表示法时,它被解释为namespace\NYTD\ReadingListBackend;,这是对常量的访问NYTD\ReadingListBackendnamespace这里的关键字解析为当前活动的命名空间,在您的情况下是全局命名空间)。

所以你的代码没有声明任何命名空间(它是全局的),只是试图访问一个常量。这就是你最终重新定义Exception.

顺便说一句,未定义的常量访问不会引发致命错误的原因是类提升。首先评估您的类声明,因此 PHP 永远不会真正达到常量访问(即使它在代码中首先出现)。

于 2012-10-26T20:42:05.333 回答
2

那么为什么我不能在命名空间声明中使用前缀呢?

根据定义,当您声明命名空间名称时,它已经完全限定的。

但是在代码的命名空间部分中,如果您需要指定完全限定的类名 (FQCN),则需要使用前缀向 PHP 发出该类名是 FQCN 的信号。

这里令人恼火的是,在您的示例中,PHP 并没有在解析时出错。我不能告诉你为什么。

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

但是 PHP 使用花括号(一个文件中有多个命名空间)会出错:

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

但是对于您的问题,我认为命名空间名称和类名称之间的区别是值得的。

于 2012-10-26T17:01:56.990 回答
1

前缀表示“根”或类似的\东西。它使限定名称空间( )成为完全限定名称空间( )。这仅在使用命名空间时有用,在声明命名空间时无效。例如:/Foo/BarFoo/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)

声明命名空间时它没有用,因为您总是从全局(“根”)命名空间声明命名空间:

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

因为每个命名空间声明都是“完全合格”的,所以 PHP 不希望\命名空间前面有 a 并给你一个错误。

于 2012-10-26T15:36:35.247 回答