在PHP中导入类和命名空间:领先的反斜杠有什么区别?

时间:2011-01-31 09:29:44

标签: php namespaces import

这两者之间有什么区别:

use Exception;
use \Exception;

或那些:

use Foo\Bar;
use \Foo\Bar;

manual说:

  

请注意,对于命名空间名称(完全   限定的命名空间名称   名称空间分隔符,例如Foo \ Bar   而不是全球名称   不是,比如FooBar),领先   反斜杠是不必要的,而不是   允许,因为输入名称必须完整   合格,不处理   相对于当前的命名空间。

但我真的不明白这一点,因为以上所有变种都有效,即绝对不是“不允许”。

查看zend_do_use显示,is_global(设置,当有反斜杠时)仅用于以下情况中的警告:

namespace {
    use Exception;
}

它告诉我:“具有非复合名称'异常'的use语句无效”。 (尽管对use \Exception做同样的事情会产生同样的影响,但不会发出警告。)

所以:我错过了什么吗?实际上有什么不同吗?

5 个答案:

答案 0 :(得分:33)

手册将反斜杠指定为不必要的,这自然意味着如果您仍然使用它,则意义相同。但是,正如您所指出的那样,手册中说它被认为是不允许的,这是错误的。

然而,手册还有其他问题。他们做广告:

// importing a global class
use \ArrayObject;

如果相对于当前命名空间未处理导入名称,则use \ArrayObjectuse ArrayObject必须具有相同的含义。 use ArrayObject除了全球之外还可以提到什么?实际上,引擎将导入全局引擎。

此外,有这样的错误: http://bugs.php.net/bug.php?id=49143

我相信对标准应该是什么感到困惑。

回答你的问题:没有区别。但是,如果我是引擎开发人员,他也是一个没有领先的斜杠标准的信徒,那么我就不需要考虑有人写use \Exception;的情况。我相信情况可能就是这样。

答案 1 :(得分:12)

事实上,在导入名称空间时使用前导反斜杠没有区别,PHP manual中的信息也发生了变化:

  

请注意,对于命名空间名称(完全限定的命名空间名称)   包含名称空间分隔符,例如Foo \ Bar而不是全局   没有的名称,如FooBar),领先的反斜杠是   不必要和不推荐,因为导入名称必须完整   限定,并且不会相对于当前命名空间进行处理。

所以现在有一些真实的信息,不建议使用前导反斜杠,但没有任何信息表明它过去是不允许的。

所以目前:

use Exception;
use \Exception;

这两行的工作原理相同,但您应该使用第一行。

答案 2 :(得分:5)

通常前导反斜杠定义标识符是绝对的。如果它缺失,则解释器假定它是相对标识符。

这是绝对标识符:

$x = new \Name\Space\To\Class();

这是一个相对标识符,因为没有前导斜杠。它与当前命名空间相关:

namespace Name\Space;
$x = new To\Class;

这也是一个相对标识符。在这种情况下,它针对use语句解析,因为最后一部分(别名)与该类的第一部分相同:

namespace Other\Name\Space;
use Name\Space;
$x = new Space\To\Class;

但是,因为在namespaceuse语句中只允许使用绝对标识符(完全限定名称),所以可以在此处省略它。在namespace中,甚至不允许设置前导反斜杠。

有关PHP如何解析不同命名空间声明的更多信息,请参阅namespace rules manual

答案 3 :(得分:-3)

不要说我们有

namespace MyNamespace
use Exception;
use \Exception;

然后第一次使用实际导入类MyNamespace \ Exception而第二次只使用主类\ Exception

所以你可以拥有像

这样的东西
namespace MyNamespace;
class Exception extends \Exception{ }

然后我可以

throw new \Exception('Exception from global namespace');
throw new \MyNamespace\Exception('Exception from MyNamespace');

答案 4 :(得分:-3)

前导反斜杠表示全局命名空间。如果您位于命名空间的范围内,则必须使用它来访问全局命名空间。例如:

namespace A
{
    class A
    {
        public function __construct()
        {
            echo('namespace: A<br />');
        }
    }
}

namespace B\A
{
    class A
    {
        public function __construct()
        {
            echo('namespace: B\\A<br />');
        }
    }
}

namespace B
{
    class B
    {
        public function __construct()
        {
            new \A\A(); // namespace: A
            new A\A(); // namespace: B\A
        }
    }
    new B();
}

使用前导反斜杠可以获得绝对路径,没有它就可以获得相对路径。