Klassen und Namespaces in PHP importieren: Welchen Unterschied macht ein führender Backslash?

Lesezeit: 5 Minuten

Benutzer-Avatar
NikiC

Was ist der Unterschied zwischen diesen beiden:

use Exception;
use \Exception;

Oder jene:

use Foo\Bar;
use \Foo\Bar;

Das Handbuch sagt:

Beachten Sie, dass für Namespace-Namen (vollqualifizierte Namespace-Namen mit Namespace-Trennzeichen wie Foo\Bar im Gegensatz zu globalen Namen ohne Namespace-Trennzeichen wie FooBar) der führende umgekehrte Schrägstrich unnötig und nicht zulässig ist, da Importnamen vollständig qualifiziert sein müssen. und werden nicht relativ zum aktuellen Namensraum verarbeitet.

Aber das verstehe ich nicht wirklich, da alle oben genannten Varianten funktionieren, dh es ist definitiv nicht “nicht erlaubt”.

Ein Blick hinein zend_do_use zeigte, dass is_global (gesetzt, wenn ein führender Backslash vorhanden ist) wird nur in folgendem Fall zur Warnung verwendet:

namespace {
    use Exception;
}

Was mir sagt: “Die use-Anweisung mit dem nicht zusammengesetzten Namen ‘Exception’ hat keine Wirkung”. (Obwohl ich dasselbe mit mache use \Exception hätte genauso wenig Wirkung, wirft aber keine Warnung.)

Also: Übersehe ich etwas? Gibt es tatsächlich einen Unterschied?

Benutzer-Avatar
Erisco

Das Handbuch gibt den Backslash als an nicht notwendig, was natürlich bedeutet, dass, wenn Sie es trotzdem verwenden, die Bedeutung äquivalent ist. Wie Sie jedoch darauf hingewiesen haben, steht im Handbuch, dass dies angeblich nicht zulässig ist, was falsch ist.

Allerdings gibt es etwas anderes beunruhigend mit der Anleitung. Sie werben damit:

// importing a global class
use \ArrayObject;

Wenn es stimmt, dass Importnamen nicht relativ zum aktuellen Namensraum verarbeitet werden, dann use \ArrayObject und use ArrayObject muss dieselbe Bedeutung haben. Was sonst könnte use ArrayObject beziehen sich auf andere als die globale? In der Praxis importiert die Engine die globale.

Auch mit Fehlern wie diesem:
http://bugs.php.net/bug.php?id=49143

Ich glaube, es herrscht Verwirrung darüber, was der Standard sein soll.

Um deine Frage zu beantworten: Es gibt keinen Unterschied. Wenn ich jedoch der Engine-Entwickler wäre, der auch an den Standard ohne führenden Schrägstrich glaubt, müsste ich keinen Fall in Betracht ziehen, in dem jemand geschrieben hat use \Exception;. Ich glaube, das war wahrscheinlich der Fall.

  • Beachten Sie, dass Sie bei einer Namespace-Klasse den Composer verwenden, um eine Klasse zu laden, indem Sie sie einfach mit ihrem “Nachnamen” (kein Namespace-Präfix) aufrufen. Verwenden Sie das MUST-Präfix mit Backslash, wenn Sie es NICHT vorher mit use aufrufen . Beispiel: \QuantumPHP::log(“some message”); es sei denn, Sie fügen “use QuantumPHP” hinzu; vor der Klassendefinition.

    – Fabien Haddadi

    19. April 2019 um 14:58 Uhr

Benutzer-Avatar
Marcin Nabiałek

Tatsächlich gibt es im Moment keinen Unterschied darin, führende Backslashes beim Importieren von Namensräumen und auch Informationen zu verwenden PHP-Handbuch hat sich verändert:

Beachten Sie, dass für Namespace-Namen (vollqualifizierte Namespace-Namen mit Namespace-Trennzeichen, wie Foo\Bar im Gegensatz zu globalen Namen, die dies nicht tun, wie FooBar) der führende umgekehrte Schrägstrich unnötig ist und nicht empfohlenda Importnamen vollständig qualifiziert sein müssen und nicht relativ zum aktuellen Namensraum verarbeitet werden.

Jetzt gibt es also echte Informationen, dass die Verwendung von führendem Backslash nicht empfohlen wird, aber es gibt keine Informationen darüber, dass dies in der Vergangenheit nicht zulässig war.

Also im Moment:

use Exception;
use \Exception;

Diese beiden Zeilen funktionieren gleich, aber Sie sollten lieber die erste verwenden.

Benutzer-Avatar
KingCrunch

Normalerweise definiert der führende Backslash, dass der Bezeichner absolut ist. Fehlt es, geht der Interpreter davon aus, dass es sich um einen relativen Bezeichner handelt.

Dies ist ein absoluter Bezeichner:

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

Aufgrund des fehlenden führenden Schrägstrichs handelt es sich um eine relative Kennung. Es ist relativ zum aktuellen Namespace:

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

Auch dies ist ein relativer Bezeichner. In diesem Fall wird gegen die entschieden use Anweisung, da der letzte Teil (Alias) derselbe ist wie der erste der Klasse:

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

Allerdings, weil im namespace und use Anweisungen sind nur absolute Bezeichner (vollqualifizierte Namen) erlaubt, es ist in Ordnung, sie hier wegzulassen. Im namespacees ist nicht einmal erlaubt, den führenden Backslash zu setzen.

Weitere Informationen darüber, wie PHP die verschiedenen Namespace-Deklarationen auflöst, finden Sie in der Handbuch für Namensraumregeln.

Der führende Backslash steht für den globalen Namensraum. Wenn Sie sich im Gültigkeitsbereich eines Namensraums befinden, müssen Sie diesen verwenden, um den globalen Namensraum zu erreichen. Zum Beispiel:

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

Mit führendem Backslash erhält man den absoluten Pfad, ohne den relativen Pfad.

Sagen wir nicht, wir haben

namespace MyNamespace
use Exception;
use \Exception;

dann importiert die erste Verwendung tatsächlich die Klasse MyNamespace\Exception und die zweite nur die Hauptklasse \Exception

damit du sowas haben kannst

namespace MyNamespace;
class Exception extends \Exception{ }

und dann kann ich

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

  • namespace Foo { class Exception extends \Exception { } use Exception as BigFoo; throw new BigFoo; } Dies wirft die globale Exception, nicht die lokale. Und das oben verlinkte Dokument sagt auch: “Importnamen müssen vollständig qualifiziert sein und werden nicht relativ zum aktuellen Namensraum verarbeitet”.

    – Nikic

    31. Januar 2011 um 10:14 Uhr


  • Das ist falsch. Das use-Anweisung verwenden Sie immer vollständig qualifizierte Namen. Deswegen use Exception; wird nicht gegen den aktuellen Namensraum aufgelöst und ist tatsächlich identisch mit use \Exception;.

    – KingCrunch

    2. Februar 2011 um 21:09 Uhr


  • namespace Foo { class Exception extends \Exception { } use Exception as BigFoo; throw new BigFoo; } Dies wirft die globale Exception, nicht die lokale. Und das oben verlinkte Dokument sagt auch: “Importnamen müssen vollständig qualifiziert sein und werden nicht relativ zum aktuellen Namensraum verarbeitet”.

    – Nikic

    31. Januar 2011 um 10:14 Uhr


  • Das ist falsch. Das use-Anweisung verwenden Sie immer vollständig qualifizierte Namen. Deswegen use Exception; wird nicht gegen den aktuellen Namensraum aufgelöst und ist tatsächlich identisch mit use \Exception;.

    – KingCrunch

    2. Februar 2011 um 21:09 Uhr


1311690cookie-checkKlassen und Namespaces in PHP importieren: Welchen Unterschied macht ein führender Backslash?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy