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

时间:2022-09-10 23:10:14

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, i.e. 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?

那么:我错过了什么吗?实际上有什么区别吗?

5 个解决方案

#1


29  

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. What else could use ArrayObject refer to other than the global one? In practice, the engine will import the global one.

如果确实没有相对于当前名称空间处理导入名称,那么使用\ ArrayObject和使用ArrayObject必须具有相同的含义。除了全局之外,还有什么可以使用ArrayObject?实际上,引擎将导入全局引擎。

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;. I believe this was likely the case.

回答你的问题:没有区别。但是,如果我是发动机开发人员,他也是无前导斜杠标准的信徒,那么我就不需要考虑有人写过使用\ Exception;的情况。我相信情况可能就是这样。

#2


9  

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.

这两行的工作方式相同但你应该使用第一行。

#3


5  

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. In namespace, it's even not allowed to set the leading backslash.

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

For further information on how PHP resolves the different namespace declarations, see the namespace rules manual.

有关PHP如何解析不同命名空间声明的更多信息,请参阅命名空间规则手册。

#4


-2  

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');

#5


-2  

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.

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

#1


29  

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. What else could use ArrayObject refer to other than the global one? In practice, the engine will import the global one.

如果确实没有相对于当前名称空间处理导入名称,那么使用\ ArrayObject和使用ArrayObject必须具有相同的含义。除了全局之外,还有什么可以使用ArrayObject?实际上,引擎将导入全局引擎。

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;. I believe this was likely the case.

回答你的问题:没有区别。但是,如果我是发动机开发人员,他也是无前导斜杠标准的信徒,那么我就不需要考虑有人写过使用\ Exception;的情况。我相信情况可能就是这样。

#2


9  

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.

这两行的工作方式相同但你应该使用第一行。

#3


5  

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. In namespace, it's even not allowed to set the leading backslash.

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

For further information on how PHP resolves the different namespace declarations, see the namespace rules manual.

有关PHP如何解析不同命名空间声明的更多信息,请参阅命名空间规则手册。

#4


-2  

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');

#5


-2  

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.

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