Come funziona la parola chiave "usa" in PHP e posso importare classi con essa?


136

Ho un file con una classe Resp. Il percorso è:

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

E ho un index.phpfile in questa directory:

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

In questo index.phpfile voglio creare un'istanza di una classe Resp.

$a = new Resp();

So che posso usare requireo includeparole chiave per includere il file con una classe:

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

Ma voglio importare le classi senza usare requireo include. Sto cercando di capire come usefunziona la parola chiave. Ho provato questi passaggi ma nulla funziona:

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

Dice:

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

Come funziona la parola chiave use? Posso usarlo per importare le classi?


1
Non puoi senza importare i file. Per favore, non cambiare il flusso. Anche gli spazi dei nomi non sono davvero utilizzati in PHP. Proprio come VB.NET
Cole Johnson il

14
@ cole-johnson, non sono d'accordo con te. Symfony è costruito attorno a namespaces. In realtà non c'è alcun Symfony se non usi gli spazi dei nomi
Green

Risposte:


80

usenon include nulla. Importa semplicemente lo spazio dei nomi (o classe) specificato nell'ambito corrente

Se desideri che le classi vengano caricate automaticamente, leggi le informazioni sul caricamento automatico


@ G-Man risponde alle stesse domande poste.
zerkms

188

No, non puoi importare una classe con la useparola chiave. Devi usare include/ requirestatement. Anche se si utilizza un caricatore automatico PHP, il caricatore automatico dovrà comunque utilizzare includeo requireinternamente.

Lo scopo dell'uso parola chiave:

Considera un caso in cui hai due classi con lo stesso nome; lo troverai strano, ma quando lavori con una grande struttura MVC, succede. Quindi, se hai due classi con lo stesso nome, inseriscile in spazi dei nomi diversi. Ora considera quando il tuo caricatore automatico sta caricando entrambe le classi (lo fa per require) e stai per usare l'oggetto della classe. In questo caso, il compilatore verrà confuso quale oggetto di classe caricare tra due. Per aiutare il compilatore a prendere una decisione, è possibile utilizzare l' useistruzione in modo che possa prendere una decisione su quale verrà utilizzato.

Oggi i principali framework usano includeo requiretramite composerepsr

1) compositore

2) Caricatore automatico PSR-4

Attraversarli può aiutarti ulteriormente. Puoi anche utilizzare un alias per indirizzare una classe esatta. Supponiamo di avere due classi con lo stesso nome, ad esempio Mailercon due spazi dei nomi diversi:

namespace SMTP;
class Mailer{}

e

namespace Mailgun;
class Mailer{}

E se si desidera utilizzare entrambe le classi Mailer contemporaneamente, è possibile utilizzare un alias.

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

Più avanti nel codice se si desidera accedere a tali oggetti di classe, è possibile effettuare le seguenti operazioni:

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

Farà riferimento alla classe originale.

Alcuni potrebbero confondersi sul fatto che allora non ci sono nomi di classe simili, quindi non c'è uso della useparola chiave. Bene, puoi usare la __autoload($class)funzione che verrà chiamata automaticamente quando l' useistruzione viene eseguita con la classe da usare come argomento e questo può aiutarti a caricare la classe al momento dell'esecuzione al volo quando e quando necessario.

Fai riferimento a questa risposta per saperne di più sul caricatore automatico di classe.


perché non usare semplicemente un nome di classe diverso?
divino

15
@divine. Le lezioni possono essere di venditori di terze parti
Dayo,

3
@divine. Cosa succede se entrambe le classi in conflitto provengono da terze parti?
Dayo,

2
@divine Per convenzione, lo spazio dei nomi sarà <vendorName> / <packageName>, in questo modo è già stato risolto. A seguito della convenzione, per packagist è impossibile accettare lo stesso nome di fornitore da qualcun altro. E packagist.org è un repository PHP utilizzato per l'installazione di pacchetti da parte del compositore.
Tpojka,

1
@root non importa, dice solo al runtime cosa deve essere usato. come se stessi guidando una macchina e segnali che ti dice di andare avanti e di rompersi, come il modo in cui le useistruzioni diranno al compilatore di caricare questo per me ora. Capito caro!
Rajan Rawal,

23

Non pensare troppo allo spazio dei nomi .

Lo spazio dei nomi è fondamentalmente solo un prefisso di classe (come la directory nel sistema operativo) per garantire l' unicità del percorso di classe .

Anche solo per chiarire le cose, l' istruzione use non sta facendo nulla solo alias dei tuoi Namespace, quindi puoi usare scorciatoie o includere Classi con lo stesso nome ma diversi Namespace nello stesso file.

Per esempio:

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

Se vuoi sapere come funzionano gli spazi dei nomi PHP e il caricamento automatico (il vecchio modo e il nuovo modo con Composer), puoi leggere il post sul blog che ho appena scritto su questo argomento: https://enterprise-level-php.com/ 2017/12 / 25 / il-magic-behind-caricamento automatico-php-files-con-composer.html


8

Dovrai includere / richiedere comunque la classe, altrimenti PHP non conoscerà lo spazio dei nomi. Tuttavia,
non è necessario farlo nello stesso file. Ad esempio, puoi farlo in un file bootstrap. (o usa un caricatore automatico, ma in realtà non è questo l'argomento)


4

È molto probabile che il problema sia necessario utilizzare un caricatore automatico che prenderà il nome della classe (rompi per '\' in questo caso) e lo associ a una struttura di directory.

Puoi consultare questo articolo sulla funzionalità di caricamento automatico di PHP. Esistono già molte implementazioni di questo tipo di funzionalità nei framework.

Ne ho effettivamente implementato uno prima. Ecco un link .


C'è comunque un problema. Ha bisogno di un modello ricorsivo per consentirgli di costruire un percorso completo. Al momento gestisce solo spazi dei nomi a livello singolo.
Tyler Carter,

3

Sono d'accordo con Green, Symfony ha bisogno di namespace, quindi perché non usarli?

Ecco come inizia una classe di controller di esempio:

namespace Acme \ DemoBundle \ Controller;

usa Symfony \ Bundle \ FrameworkBundle \ Controller \ Controller;

class WelcomeController estende il controller {...}


3

Posso usarlo per importare le classi?

Non puoi farlo in questo modo oltre agli esempi sopra. Puoi anche usare la parola chiave useall'interno delle classi per importare tratti , in questo modo:

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'

3

La useparola chiave è per l'aliasing in PHP e non importa le classi. Questo aiuta davvero
1) Quando si hanno classi con lo stesso nome in spazi dei nomi diversi
2) Evitare di utilizzare più volte un nome di classe molto lungo.


2

Lo spazio dei nomi viene utilizzato per definire il percorso di un file specifico contenente una classe, ad es

namespace album/className; 

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

Puoi quindi includere questa classe specifica in un altro file php usando la parola chiave "usa" in questo modo:

use album/className;

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

NOTA: non utilizzare il percorso del file contenente la classe da implementare, estensioni di utilizzo per creare un'istanza di un oggetto ma utilizzare solo lo spazio dei nomi.


2

L'uso della parola chiave "use" serve per abbreviare i letterali dello spazio dei nomi. È possibile utilizzare entrambi con aliasing e senza di essa. Senza alias è necessario utilizzare l'ultima parte dello spazio dei nomi completo.

<?php
    use foo\bar\lastPart;
    $obj=new lastPart\AnyClass(); //If there's not the line above, a fatal error will be encountered.
?>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.