Bagaimana cara kerja kata kunci "menggunakan" di PHP dan dapatkah saya mengimpor kelas dengannya?

140

Saya memiliki file dengan kelas Resp. Jalannya adalah:

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

Dan saya memiliki index.phpfile di direktori ini:

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

Dalam index.phpfile ini saya ingin membuat instance kelas Resp.

$a = new Resp();

Saya tahu saya dapat menggunakan requireatau includekata kunci untuk menyertakan file dengan kelas:

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

Tapi saya ingin mengimpor kelas tanpa menggunakan requireatau include. Saya mencoba memahami cara usekerja kata kunci. Saya mencoba langkah-langkah ini tetapi tidak ada yang berhasil:

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

Ia mengatakan:

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

Bagaimana cara usekerja kata kunci ? Bisakah saya menggunakannya untuk mengimpor kelas?

hijau
sumber
1
Anda tidak bisa tanpa mengimpor file. Tolong jangan ubah alirannya. Juga ruang nama benar-benar tidak digunakan di PHP. Sama seperti VB.NET
Cole Johnson
14
@ Cole-johnson, tidak setuju dengan Anda. Symfony dibangun di sekitar namespaces. Sebenarnya tidak ada Symfony jika Anda tidak menggunakan namespace
Hijau

Jawaban:

86

usetidak termasuk apapun. Ini hanya mengimpor namespace (atau kelas) yang ditentukan ke cakupan saat ini

Jika Anda ingin kelas dimuat otomatis - baca tentang pemuatan otomatis

zerkms
sumber
@ G-Man menjawab semua pertanyaan yang diajukan.
zerkms
191

Tidak, Anda tidak dapat mengimpor kelas dengan usekata kunci. Anda harus menggunakan include/ requirestatement. Bahkan jika Anda menggunakan pemuat otomatis PHP, pemuat otomatis masih harus menggunakan baik includeatau secara requireinternal.

Tujuan penggunaan kata kunci:

Pertimbangkan kasus di mana Anda memiliki dua kelas dengan nama yang sama; Anda akan merasa aneh, tetapi ketika Anda bekerja dengan struktur MVC yang besar, hal itu terjadi. Jadi jika Anda memiliki dua kelas dengan nama yang sama, letakkan di ruang nama yang berbeda. Sekarang pertimbangkan kapan auto loader Anda memuat kedua kelas (dilakukan oleh require), dan Anda akan menggunakan objek kelas. Dalam kasus ini, kompilator akan bingung memilih objek kelas mana yang akan dimuat di antara dua objek kelas. Untuk membantu compiler membuat keputusan, Anda dapat menggunakan usepernyataan tersebut sehingga dapat membuat keputusan mana yang akan digunakan.

Saat ini kerangka kerja utama memang menggunakan includeatau requirevia composerdanpsr

1) komposer

2) Pemuat otomatis PSR-4

Menelaahnya dapat membantu Anda lebih jauh. Anda juga dapat menggunakan alias untuk menangani kelas yang tepat. Misalkan Anda memiliki dua kelas dengan nama yang sama, katakanlah Mailerdengan dua ruang nama yang berbeda:

namespace SMTP;
class Mailer{}

dan

namespace Mailgun;
class Mailer{}

Dan jika Anda ingin menggunakan kedua kelas Mailer secara bersamaan, Anda dapat menggunakan alias.

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

Nanti di kode Anda jika Anda ingin mengakses objek kelas tersebut maka Anda dapat melakukan hal berikut:

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

Ini akan mereferensikan kelas aslinya.

Beberapa mungkin bingung bahwa jika tidak ada nama kelas yang mirip maka tidak ada penggunaan usekata kunci. Nah, Anda dapat menggunakan __autoload($class)fungsi yang akan dipanggil secara otomatis ketika usepernyataan dieksekusi dengan kelas untuk digunakan sebagai argumen dan ini dapat membantu Anda memuat kelas pada saat run-time dengan cepat jika diperlukan.

Lihat jawaban ini untuk mengetahui lebih lanjut tentang pemuat otomatis kelas.

Rajan Rawal
sumber
mengapa tidak menggunakan nama kelas yang berbeda saja?
ilahi
16
@bayu_joo Kelas mungkin berasal dari vendor pihak ketiga
Dayo
3
@bayu_joo Bagaimana jika kedua kelas yang bertabrakan berasal dari pihak ke-3?
Dayo
2
@divine Menurut konvensi, namespace akan menjadi <vendorName> / <packageName> sehingga hal itu sudah diselesaikan. Mengikuti konvensi, tidak mungkin bagi pembuat paket untuk menerima nama vendor yang sama dari orang lain. Dan packagist.org adalah repositori PHP yang digunakan untuk instalasi komposer paket.
Tpojka
1
@root tidak masalah, ini hanya memberi tahu waktu proses apa yang akan digunakan. seperti Anda sedang mengendarai mobil dan sinyal memberi tahu Anda menabrak ke depan dan Anda putus, seperti usepernyataan cara akan memberi tahu kompiler memuat ini untuk saya sekarang. Oke sayang!
Rajan Rawal
24

Jangan terlalu memikirkan apa itu Namespace .

Namespace pada dasarnya hanyalah awalan Kelas (seperti direktori di Sistem Operasi) untuk memastikan keunikan jalur Kelas .

Juga hanya untuk memperjelas, pernyataan use tidak melakukan apapun hanya aliasing Namespaces Anda sehingga Anda dapat menggunakan pintasan atau menyertakan Kelas dengan nama yang sama tetapi Namespace berbeda dalam file yang sama.

Misalnya:

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

Jika Anda ingin mengetahui cara kerja PHP Namespaces dan autoloading (cara lama dan juga cara baru dengan Composer), Anda dapat membaca postingan blog yang baru saja saya tulis tentang topik ini: https://enterprise-level-php.com/ 2017/12/25 / the-magic-behind-autoloading-php-files-using-composer.html

Lukas Lukac
sumber
8

Anda harus menyertakan / memerlukan kelas, jika tidak PHP tidak akan tahu tentang namespace.
Anda tidak perlu melakukannya di file yang sama . Anda dapat melakukannya dalam file bootstrap misalnya. (atau gunakan autoloader, tapi sebenarnya bukan itu topiknya)

Samy Dindane
sumber
4

Masalahnya kemungkinan besar Anda perlu menggunakan pemuat otomatis yang akan mengambil nama kelas (putus dengan '\' dalam kasus ini) dan memetakannya ke struktur direktori.

Anda dapat melihat artikel ini tentang fungsionalitas pemuatan otomatis PHP. Ada banyak implementasi dari jenis fungsionalitas ini dalam kerangka kerja.

Saya sebenarnya telah menerapkannya sebelumnya. Ini tautannya .

Tyler Carter
sumber
Namun ada masalah dengan itu. Dibutuhkan model rekursif untuk memungkinkannya membangun jalur penuh. Sekarang ini hanya menangani ruang nama tingkat tunggal.
Tyler Carter
3

Saya setuju dengan Green, Symfony membutuhkan namespace, jadi mengapa tidak menggunakannya?

Beginilah cara kelas contoh pengontrol dimulai:

namespace Acme \ DemoBundle \ Controller;

gunakan Symfony \ Bundle \ FrameworkBundle \ Controller \ Controller;

class WelcomeController memperluas Controller {...}

Eric Draven
sumber
3

Bisakah saya menggunakannya untuk mengimpor kelas?

Anda tidak dapat melakukannya seperti itu selain contoh di atas. Anda juga dapat menggunakan kata kunci usedi dalam kelas untuk mengimpor sifat , seperti ini:

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
sumber
3

Kata usekuncinya adalah untuk aliasing di PHP dan tidak mengimpor kelas. Ini sangat membantu
1) Ketika Anda memiliki kelas dengan nama yang sama di ruang nama yang berbeda
2) Hindari menggunakan nama kelas yang sangat panjang berulang kali.

Abdul Mannan
sumber
2

Namespace digunakan untuk menentukan jalur ke file tertentu yang berisi kelas misalnya

namespace album/className; 

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

Anda kemudian dapat memasukkan kelas khusus ini ke dalam file php lain dengan menggunakan kata kunci "gunakan" seperti ini:

use album/className;

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

CATATAN: Jangan gunakan jalur ke file yang berisi kelas yang akan diimplementasikan, memperluas penggunaan untuk membuat instance objek tetapi hanya menggunakan namespace.

Dotun Peter
sumber
2

Menggunakan kata kunci "gunakan" untuk mempersingkat literal namespace. Anda dapat menggunakan keduanya dengan aliasing dan tanpa aliasing. Tanpa aliasing Anda harus menggunakan bagian terakhir dari namespace lengkap.

<?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
sumber