Importing classes and namespaces in PHP: What difference does a leading backslash make?
Asked Answered
H

5

55

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.

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:

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.)

So: Am I missing something? Is there actually some difference?

Heptad answered 31/1, 2011 at 9:29 Comment(0)
E
40

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.

Also, with bugs such as this: 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.

Eleonoreeleoptene answered 2/2, 2011 at 20:8 Comment(1)
Note that if a namespaced class, you're using composer to load a class by just calling it by its "last" name (no namespace prefix), use MUST prefix with backslash if you're NOT going to invoke it with use before hand. Example: \QuantumPHP::log("some message"); unless you add "use QuantumPHP;" before the class definition.Earthaearthborn
S
17

In fact there is no difference in using leading backslash in importing namespaces at the moment and also information in PHP manual has changed:

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.

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.

Stereotype answered 7/7, 2014 at 10:47 Comment(0)
P
8

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:

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.

Paphos answered 2/2, 2011 at 20:40 Comment(0)
Z
-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.

Zwinglian answered 8/2, 2011 at 8:41 Comment(2)
That is the most confusing example I've ever seen.Abutment
Btw. there was no "use" keyword when I wrote that. The "B\A" namespace with "A" class was a funny choice. :D I have excellent talent in variable naming... :DZwinglian
C
-3

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

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');
Cerracchio answered 31/1, 2011 at 10:8 Comment(2)
namespace Foo { class Exception extends \Exception { } use Exception as BigFoo; throw new BigFoo; } This throws the global Exception, not the local one. And the above linked docu says too: "import names must be fully qualified, and are not processed relative to the current namespace".Heptad
Thats wrong. The use-statement always use full qualified names. Therefore use Exception; is not resolved against the current namespace and actually is the same as use \Exception;.Paphos

© 2022 - 2024 — McMap. All rights reserved.