简体   繁体   English

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

[英]Importing classes and namespaces in PHP: What difference does a leading backslash make?

What's the difference between those two: 这两者有什么区别:

use Exception;
use \Exception;

Or those: 或那些:

use Foo\Bar;
use \Foo\Bar;

The manual says: 手册说:

Note that for namespaced names (fully qualified namespace names containing namespace separator, such as Foo\\Bar as opposed to global names that do not, such as FooBar), the leading backslash is unnecessary and not allowed, as import names must be fully qualified, and are not processed relative to the current namespace. 请注意,对于名称空间名称(包含名称空间分隔符的完全限定名称空间名称,例如Foo \\ Bar而不是全局名称,例如FooBar),前导反斜杠是不必要的,不允许,因为导入名称必须是完全限定的,并且不会相对于当前名称空间进行处理。

But I don't really understand this, as all of the above variants work, ie it definitely is not "not allowed". 但我并不是真的理解这一点,因为所有上述变种都有效,即它绝对不是“不允许”。

A look into zend_do_use showed, that is_global (set, when there is a leading backslash) is only used for a warning in the following case: 看看zend_do_use显示, is_global (设置,当有前导反斜杠时)仅用于以下情况中的警告:

namespace {
    use Exception;
}

Which tells me: "The use statement with non-compound name 'Exception' has no effect". 这告诉我:“具有非复合名称的'使用声明'异常'无效”。 (Though doing the same with use \\Exception would have just as little effect, but does not throw a warning.) (虽然use \\Exception做同样的效果,但不会发出警告。)

So: Am I missing something? 那么:我错过了什么吗? Is there actually some difference? 实际上有什么区别吗?

The manual specifies the backslash as unnecessary , which naturally means that if you still use it that the meaning is equivalent. 手册指定反斜杠是不必要的 ,这自然意味着如果你仍然使用它,意思是等价的。 However, as you have pointed out, the manual says that it is supposedly not allowed, which is false. 但是,正如您所指出的那样,手册中说它应该是不允许的,这是错误的。

However, there is something else troubling with the manual. 但是,手册还有其他问题。 They advertise this: 他们做广告:

// importing a global class
use \ArrayObject;

If it is true that import names are not processed relative to the current namespace, then use \\ArrayObject and use ArrayObject must have the same meaning. 如果确实没有相对于当前名称空间处理导入名称,那么use \\ArrayObjectuse ArrayObject必须具有相同的含义。 What else could use ArrayObject refer to other than the global one? 还有什么可以use ArrayObject而不是全局的? In practice, the engine will import the global one. 实际上,引擎将导入全局引擎。

Also, with bugs such as this: http://bugs.php.net/bug.php?id=49143 此外,还有这样的错误: http//bugs.php.net/bug.php?id = 49143

I believe there is confusion over what the standard is supposed to be. 我相信这个标准应该是什么样的混乱。

To answer your question: there is no difference. 回答你的问题:没有区别。 However, if I was the engine developer who was also a believer of the no-leading-slash standard, then I wouldn't need to consider a case where someone wrote use \\Exception; 但是,如果我是引擎开发人员,他也是无主导斜杠标准的信徒,那么我就不需要考虑有人编写use \\Exception; . I believe this was likely the case. 我相信情况可能就是这样。

In fact there is no difference in using leading backslash in importing namespaces at the moment and also information in PHP manual has changed: 实际上,在导入名称空间时使用前导反斜杠没有区别, PHP手册中的信息也发生了变化:

Note that for namespaced names (fully qualified namespace names containing namespace separator, such as Foo\\Bar as opposed to global names that do not, such as FooBar), the leading backslash is unnecessary and not recommended , as import names must be fully qualified, and are not processed relative to the current namespace. 请注意,对于命名空间名称(包含命名空间分隔符的完全限定的命名空间名称,例如Foo \\ Bar而不是全局名称,例如FooBar),前导反斜杠是不必要的, 不建议使用 ,因为导入名称必须是完全限定的,并且不会相对于当前名称空间进行处理。

So now there is true information that using leading backslash is not recommended but there is no info that it's not allowed at it was in past. 所以现在有一些真实的信息,不推荐使用前导反斜杠,但没有任何信息表明过去它是不允许的。

So at the moment: 所以目前:

use Exception;
use \Exception;

those 2 lines work the same but you should rather use the first one. 这两行的工作方式相同但你应该使用第一行。

Usually the leading backslash defines, that the identifier is absolute. 通常,前导反斜杠定义标识符是绝对的。 If its missing, the interpreter assumes, that it is a relative identifier. 如果它缺失,则解释器假定它是相对标识符。

This is an absolute identifier: 这是绝对标识符:

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

This is a relative identifier, because of the no leading slash. 这是一个相对标识符,因为没有前导斜杠。 It's relative to the current namespace: 它与当前命名空间相关:

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

This is also a relative identifier. 这也是一个相对标识符。 In this case, its resolved against the use statement, because the last part (alias) is the same, as the first of the class: 在这种情况下,它针对use语句解析,因为最后一部分(别名)与第一个类相同:

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

However, because in namespace and use statements only absolute identifiers (fully qualified names) are allowed, it's ok to omit it here. 但是,因为在namespaceuse语句中只允许use绝对标识符(完全限定名称),所以可以在此处省略它。 In namespace , it's even not allowed to set the leading backslash. namespace ,甚至不允许设置前导反斜杠。

For further information on how PHP resolves the different namespace declarations, see the namespace rules manual . 有关PHP如何解析不同命名空间声明的更多信息,请参阅命名空间规则手册

le't say we have 不要说我们有

namespace MyNamespace
use Exception;
use \Exception;

then the first use actually imports class MyNamespace\\Exception and the second one just the main class \\Exception 然后第一次使用实际导入类MyNamespace \\ Exception,第二次只使用主类\\ Exception

so you can have something like 所以你可以拥有类似的东西

namespace MyNamespace;
class Exception extends \Exception{ }

and then I can 然后我可以

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

The leading backslash means the global namespace. 前导反斜杠表示全局命名空间。 If you are in a namespace's scope, you have to use that to reach the global namespace. 如果您位于命名空间的范围内,则必须使用它来访问全局命名空间。 For example: 例如:

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();
}

With leading backslash you got the absolute path, and without it you got the relative path. 使用前导反斜杠可以获得绝对路径,没有它就可以获得相对路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM