Jak działa słowo kluczowe „use” w PHP i czy mogę za jego pomocą importować klasy?

136

Mam plik z klasą Resp. Ścieżka to:

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

Mam index.phpplik w tym katalogu:

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

W tym index.phppliku chcę utworzyć instancję klasy Resp.

$a = new Resp();

Wiem, że mogę użyć słów kluczowych requirelub, includeaby dołączyć plik do klasy:

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

Ale chcę zaimportować klasy bez użycia requirelub include. Próbuję zrozumieć, jak usedziała słowo kluczowe. Wypróbowałem te kroki, ale nic nie działa:

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

To mówi:

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

Jak działa słowo kluczowe use? Czy mogę go używać do importowania klas?

Zielony
źródło
1
Nie możesz bez importowania plików. Proszę, nie zmieniaj przepływu. Również przestrzenie nazw naprawdę nie są używane w PHP. Podobnie jak VB.NET
Cole Johnson,
13
@ cole-johnson, nie zgadzam się z tobą. Symfony jest zbudowany wokół namespaces. W rzeczywistości nie ma żadnej Symfony, jeśli nie używasz przestrzeni nazw
Green

Odpowiedzi:

80

usenie zawiera niczego. Po prostu importuje określoną przestrzeń nazw (lub klasę) do bieżącego zakresu

Jeśli chcesz, aby klasy były ładowane automatycznie - przeczytaj o automatycznym ładowaniu

zerkms
źródło
@ G-Man odpowiada na same pytania.
zerkms
188

Nie, nie możesz zaimportować zajęć ze usesłowem kluczowym. Musisz użyć include/ requireoświadczenie. Nawet jeśli używasz auto ładowarka PHP, nadal autoloader będzie musiał użyć jednej includelub requirewewnętrznie.

Słowo kluczowe Cel użycia :

Rozważmy przypadek, w którym masz dwie klasy o tej samej nazwie; wyda się to dziwne, ale zdarza się, gdy pracujesz z dużą strukturą MVC. Więc jeśli masz dwie klasy o tej samej nazwie, umieść je w różnych przestrzeniach nazw. Zastanów się teraz, kiedy twój automatyczny program ładujący ładuje obie klasy (robi przez require) i masz zamiar użyć obiektu klasy. W takim przypadku kompilator pomyli się, który obiekt klasy załadować spośród dwóch. Aby pomóc kompilatorowi w podjęciu decyzji, możesz użyć useinstrukcji, aby mógł podjąć decyzję, na której z nich zostanie użyty.

Obecnie główne frameworki używają includelub requireza pośrednictwem composeripsr

1) kompozytor

2) autoloader PSR-4

Przejrzenie ich może pomóc ci dalej. Możesz również użyć aliasu, aby zaadresować dokładną klasę. Załóżmy, że masz dwie klasy o tej samej nazwie, powiedzmy Mailerz dwiema różnymi przestrzeniami nazw:

namespace SMTP;
class Mailer{}

i

namespace Mailgun;
class Mailer{}

A jeśli chcesz używać obu klas Mailer w tym samym czasie, możesz użyć aliasu.

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

W dalszej części kodu, jeśli chcesz uzyskać dostęp do tych obiektów klas, możesz wykonać następujące czynności:

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

Będzie odnosić się do oryginalnej klasy.

Niektórzy mogą się pomylić, że w takim razie nie ma podobnych nazw klas, to nie ma zastosowania usesłowa kluczowego. Cóż, możesz użyć __autoload($class)funkcji, która zostanie wywołana automatycznie, gdy useinstrukcja zostanie wykonana z klasą, która ma być użyta jako argument, a to może pomóc ci załadować klasę w czasie wykonywania w locie, gdy zajdzie taka potrzeba.

Zapoznaj się z tą odpowiedzią, aby dowiedzieć się więcej o autoloaderze klas.

Rajan Rawal
źródło
dlaczego nie użyć po prostu innej nazwy klasy?
boski
15
@boski. Zajęcia mogą być prowadzone przez zewnętrznych dostawców
Dayo
3
@boski. Co się stanie, jeśli obie kolidujące ze sobą klasy są ze stron trzecich?
Dayo
2
@divine Zgodnie z konwencją, przestrzeń nazw będzie miała postać <vendorName> / <packageName>, więc została już rozwiązana. Zgodnie z konwencją, paczkista nie może zaakceptować tej samej nazwy sprzedawcy od kogoś innego. A packagist.org to repozytorium PHP, które jest używane do instalacji pakietów przez kompozytora.
Tpojka
1
@root nie ma znaczenia, po prostu mówi programowi, czego należy użyć. tak jak prowadzisz samochód i sygnał mówi, że uderzasz do przodu i się zepsujesz, jak useinstrukcja way powie kompilatorowi załaduj to teraz. Mam to kochanie!
Rajan Rawal,
23

Nie zastanawiaj się zbytnio, czym jest przestrzeń nazw .

Przestrzeń nazw jest po prostu prefiksem klasy (jak katalog w systemie operacyjnym), aby zapewnić niepowtarzalność ścieżki klasy .

Również dla jasności, instrukcja use nie robi nic tylko aliasowania twoich przestrzeni nazw, dzięki czemu można używać skrótów lub dołączać klasy o tej samej nazwie, ale o różnych przestrzeniach nazw w tym samym pliku.

Na przykład:

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

Jeśli chcesz wiedzieć, jak działają przestrzenie nazw PHP i automatyczne ładowanie (stary i nowy sposób z Composerem), możesz przeczytać wpis na blogu, który właśnie napisałem na ten temat: https://enterprise-level-php.com/ 2017/12/25 / the-magic-behind-autoloading-files-using-composer.html

Lukas Lukac
źródło
8

I tak będziesz musiał dołączyć / wymagać klasy, w przeciwnym razie PHP nie będzie wiedziało o przestrzeni nazw.
Nie musisz jednak robić tego w tym samym pliku. Możesz to zrobić na przykład w pliku bootstrap. (lub użyj autoloadera, ale nie o to właściwie chodzi)

Samy Dindane
źródło
4

Najprawdopodobniej będziesz musiał użyć automatycznego programu ładującego, który przyjmie nazwę klasy (w tym przypadku podziel na '\') i zamapuje ją na strukturę katalogów.

Możesz zapoznać się z tym artykułem na temat funkcji automatycznego ładowania w PHP. Istnieje już wiele implementacji tego typu funkcjonalności w frameworkach.

Właściwie to wdrożyłem już wcześniej. Oto link .

Tyler Carter
źródło
Jest z tym jednak problem. Potrzebuje modelu rekurencyjnego, aby umożliwić zbudowanie pełnej ścieżki. Obecnie obsługuje tylko przestrzenie nazw jednopoziomowe.
Tyler Carter
3

Zgadzam się z Greenem, Symfony potrzebuje przestrzeni nazw, więc dlaczego ich nie użyć?

Tak zaczyna się przykładowa klasa kontrolera:

przestrzeń nazw Acme \ DemoBundle \ Controller;

użyj Symfony \ Bundle \ FrameworkBundle \ Controller \ Controller;

class WelcomeController rozszerza Controller {...}

Eric Draven
źródło
3

Czy mogę go używać do importowania klas?

Nie możesz tego zrobić w ten sposób poza powyższymi przykładami. Możesz również użyć słowa kluczowego usewewnątrz klas, aby zaimportować cechy , na przykład:

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
źródło
3

Słowo usekluczowe służy do tworzenia aliasów w PHP i nie importuje klas. To naprawdę pomaga
1) Gdy masz klasy o tej samej nazwie w różnych przestrzeniach nazw
2) Unikaj ciągłego używania naprawdę długich nazw klas.

Abdul Mannan
źródło
2

Przestrzeń nazw służy do zdefiniowania ścieżki do konkretnego pliku zawierającego klasę np

namespace album/className; 

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

Następnie możesz dołączyć tę konkretną klasę do innego pliku php, używając słowa kluczowego „użyj” w następujący sposób:

use album/className;

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

UWAGA: Nie używaj ścieżki do pliku zawierającego klasę, która ma być implementowana, rozszerza użycie do utworzenia instancji obiektu, ale użyj tylko przestrzeni nazw.

Dotun Peter
źródło
2

Użycie słowa kluczowego „use” służy do skracania literałów przestrzeni nazw. Możesz używać zarówno z aliasowaniem, jak i bez niego. Bez aliasingu musisz użyć ostatniej części pełnej przestrzeni nazw.

<?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
źródło