Wie funktioniert das Schlüsselwort "use" in PHP und kann ich damit Klassen importieren?

136

Ich habe eine Datei mit einer Klasse Resp. Der Weg ist:

C:\xampp\htdocs\One\Classes\Resp.php

Und ich habe eine index.phpDatei in diesem Verzeichnis:

C:\xampp\htdocs\Two\Http\index.php

In dieser index.phpDatei möchte ich eine Klasse instanziieren Resp.

$a = new Resp();

Ich weiß, dass ich requireoder includeSchlüsselwörter verwenden kann, um die Datei in eine Klasse aufzunehmen:

require("One\Classes\Resp.php");       // I've set the include_path correctly already ";C:\xampp\htdocs". It works.
$a = new Resp();

Aber ich möchte Klassen importieren, ohne requireoder zu verwenden include. Ich versuche zu verstehen, wie useKeyword funktioniert. Ich habe diese Schritte ausprobiert, aber nichts funktioniert:

use One\Classes\Resp;
use xampp\htdocs\One\Classes\Resp;
use htdocs\One\Classes\Resp;
use One\Classes;
use htdocs\One\Classes;    /* nothing works */

$a = new Resp();

Es sagt:

Fatal error: Class 'One\Classes\Resp' not found in C:\xampp\htdocs\Two\Http\index.php

Wie funktioniert das Keyword use? Kann ich damit Klassen importieren?

Grün
quelle
1
Sie können nicht ohne den Import der Dateien. Bitte ändern Sie den Fluss nicht. Auch Namespaces werden in PHP wirklich nicht verwendet. Genau wie VB.NET
Cole Johnson
13
@ Cole-Johnson, stimme dir nicht zu. Symfony basiert auf namespaces. In der Tat gibt es keine Symfony, wenn Sie keine Namespaces verwenden
Green

Antworten:

80

usebeinhaltet nichts. Es wird nur der angegebene Namespace (oder die angegebene Klasse) in den aktuellen Bereich importiert

Wenn Sie möchten, dass die Klassen automatisch geladen werden, lesen Sie mehr über das automatische Laden

zerkms
quelle
@ G-Man beantwortet genau die gestellten Fragen.
Zerkms
188

Nein, Sie können keine Klasse mit dem useSchlüsselwort importieren . Sie müssen include/ requireAnweisung verwenden. Selbst wenn Sie einen PHP-Auto-Loader verwenden, muss der Autoloader entweder includeoder requireintern verwendet werden.

Das Schlüsselwort für den Verwendungszweck :

Stellen Sie sich einen Fall vor, in dem Sie zwei Klassen mit demselben Namen haben. Sie werden es seltsam finden, aber wenn Sie mit einer großen MVC-Struktur arbeiten, passiert es. Wenn Sie also zwei Klassen mit demselben Namen haben, platzieren Sie sie in unterschiedlichen Namespaces. Überlegen Sie nun, wann Ihr Auto Loader beide Klassen lädt (bis require) und Sie im Begriff sind, ein Objekt der Klasse zu verwenden. In diesem Fall wird der Compiler verwirrt, welches Klassenobjekt unter zwei geladen werden soll. Um dem Compiler zu helfen, eine Entscheidung zu treffen, können Sie die useAnweisung verwenden, damit er eine Entscheidung treffen kann, für welche verwendet werden soll.

Heutzutage verwenden große Frameworks includeoder requirevia composerundpsr

1) Komponist

2) PSR-4 Autoloader

Das Durchgehen kann Ihnen weiterhelfen. Sie können auch einen Alias ​​verwenden, um eine genaue Klasse zu adressieren. Angenommen, Sie haben zwei Klassen mit demselben Namen, beispielsweise Mailermit zwei verschiedenen Namespaces:

namespace SMTP;
class Mailer{}

und

namespace Mailgun;
class Mailer{}

Wenn Sie beide Mailer-Klassen gleichzeitig verwenden möchten, können Sie einen Alias ​​verwenden.

use SMTP\Mailer as SMTPMailer;
use Mailgun\Mailer as MailgunMailer;

Wenn Sie später in Ihrem Code auf diese Klassenobjekte zugreifen möchten, können Sie Folgendes tun:

$smtp_mailer = new SMTPMailer;
$mailgun_mailer = new MailgunMailer;

Es wird auf die ursprüngliche Klasse verweisen.

Einige können verwirrt sein, dass es dann keine ähnlichen Klassennamen gibt, dann gibt es keine Verwendung von useSchlüsselwörtern. Nun, Sie können eine __autoload($class)Funktion verwenden, die automatisch aufgerufen wird, wenn die useAnweisung mit der Klasse ausgeführt wird, die als Argument verwendet werden soll. Dies kann Ihnen dabei helfen, die Klasse bei Bedarf sofort zur Laufzeit zu laden.

In dieser Antwort erfahren Sie mehr über den Klassen-Autoloader.

Rajan Rawal
quelle
Warum nicht einfach einen anderen Klassennamen verwenden?
göttlich
15
@göttlich. Die Klassen können von Drittanbietern sein
Dayo
3
@göttlich. Was ist, wenn beide kollidierenden Klassen von Dritten stammen?
Dayo
2
@divine Konventionell lautet der Namespace <VendorName> / <Paketname>, sodass er bereits gelöst wurde. Gemäß der Konvention ist es für Packagisten unmöglich, denselben Anbieternamen von jemand anderem zu akzeptieren. Und packagist.org ist ein PHP-Repository, das für die Composer-Installation von Paketen verwendet wird.
Tpojka
1
@root spielt keine Rolle, es sagt nur zur Laufzeit, was verwendet werden soll. Als ob du ein Auto fährst und signalisierst, dass du vorwärts kommst und du brichst, wie die useAnweisung sagt, dass der Compiler dies jetzt für mich lädt. Verstanden, Schatz!
Rajan Rawal
23

Überdenken Sie nicht, was ein Namespace ist.

Der Namespace ist im Grunde nur ein Klassenpräfix (wie das Verzeichnis im Betriebssystem), um die Eindeutigkeit des Klassenpfads sicherzustellen .

Um die Dinge klarer zu machen, führt die use- Anweisung nicht nur ein Aliasing Ihrer Namespaces durch, sodass Sie Verknüpfungen verwenden oder Klassen mit demselben Namen, aber unterschiedlichen Namespace in dieselbe Datei aufnehmen können.

Z.B:

// You can do this at the top of your Class
use Symfony\Component\Debug\Debug;

if ($_SERVER['APP_DEBUG']) {
    // So you can utilize the Debug class it in an elegant way
    Debug::enable();
    // Instead of this ugly one
    // \Symfony\Component\Debug\Debug::enable();
}

Wenn Sie wissen möchten, wie PHP-Namespaces und das automatische Laden (sowohl der alte als auch der neue Weg mit Composer) funktionieren, können Sie den Blog-Beitrag lesen, den ich gerade zu diesem Thema geschrieben habe: https://enterprise-level-php.com/ 2017/12/25 / die Magie hinter dem automatischen Laden von PHP-Dateien mit Composer.html

Lukas Lukac
quelle
8

Sie müssen die Klasse trotzdem einschließen / benötigen, sonst weiß PHP nichts über den Namespace.
Sie müssen dies jedoch nicht in derselben Datei tun . Sie können dies beispielsweise in einer Bootstrap-Datei tun. (oder verwenden Sie einen Autoloader, aber das ist eigentlich nicht das Thema)

Samy Dindane
quelle
4

Das Problem ist höchstwahrscheinlich, dass Sie einen Auto Loader verwenden müssen, der den Namen der Klasse (in diesem Fall durch '\' unterbrechen) verwendet und einer Verzeichnisstruktur zuordnet.

Sie können diesen Artikel über das automatische Laden lesen Funktionalität von PHP . Es gibt bereits viele Implementierungen dieser Art von Funktionalität in Frameworks.

Ich habe tatsächlich schon einmal einen implementiert. Hier ist ein Link .

Tyler Carter
quelle
Es gibt jedoch ein Problem damit. Es benötigt ein rekursives Modell, damit es einen vollständigen Pfad aufbauen kann. Derzeit werden nur einstufige Namespaces verarbeitet.
Tyler Carter
3

Ich stimme Green zu, Symfony benötigt einen Namespace. Warum also nicht?

So beginnt eine Beispiel-Controller-Klasse:

Namespace Acme \ DemoBundle \ Controller;

Verwenden Sie Symfony \ Bundle \ FrameworkBundle \ Controller \ Controller.

Klasse WelcomeController erweitert Controller {...}

Eric Draven
quelle
3

Kann ich damit Klassen importieren?

Sie können es nicht so machen, außer den obigen Beispielen. Sie können das Schlüsselwort auch usein Klassen verwenden, um Merkmale wie folgt zu importieren :

trait Stuff {
    private $baz = 'baz';
    public function bar() {
        return $this->baz;
    }
}

class Cls {
    use Stuff;  // import traits like this
}

$foo = new Cls;
echo $foo->bar(); // spits out 'baz'
Thielicious
quelle
3

Das useSchlüsselwort dient zum Aliasing in PHP und importiert die Klassen nicht. Dies hilft wirklich
1) Wenn Sie Klassen mit demselben Namen in verschiedenen Namespaces haben
2) Vermeiden Sie es, immer wieder sehr lange Klassennamen zu verwenden.

Abdul Mannan
quelle
2

Der Namespace wird verwendet, um den Pfad zu einer bestimmten Datei zu definieren, die eine Klasse enthält, z

namespace album/className; 

class className{
//enter class properties and methods here
}

Sie können diese bestimmte Klasse dann in eine andere PHP-Datei aufnehmen, indem Sie das Schlüsselwort "use" wie folgt verwenden:

use album/className;

class album extends classname {
//enter class properties and methods
}

ANMERKUNG: Verwenden Sie nicht den Pfad zu der Datei, die die zu implementierende Klasse enthält, sondern erweitern Sie die Verwendung, um ein Objekt zu instanziieren, sondern verwenden Sie nur den Namespace.

Dotun Peter
quelle
2

Die Verwendung des Schlüsselworts "use" dient zum Kürzen von Namespace-Literalen. Sie können sowohl mit als auch ohne Aliasing verwenden. Ohne Aliasing müssen Sie den letzten Teil des vollständigen Namespace verwenden.

<?php
    use foo\bar\lastPart;
    $obj=new lastPart\AnyClass(); //If there's not the line above, a fatal error will be encountered.
?>
Müseyib Ələkbər
quelle