คำหลัก“ ใช้” ทำงานอย่างไรใน PHP และฉันสามารถอิมพอร์ตคลาสด้วยได้อย่างไร?


136

Respฉันมีไฟล์ที่มีชั้นเรียน เส้นทางคือ:

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

และฉันมีindex.phpไฟล์ในไดเรกทอรีนี้:

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

ในการนี้ไฟล์ผมอยากจะยกตัวอย่างชั้นเรียนindex.phpResp

$a = new Resp();

ฉันรู้ว่าฉันสามารถใช้requireหรือincludeคำหลักเพื่อรวมไฟล์กับคลาส:

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

แต่ผมต้องการที่จะเรียนนำเข้าโดยไม่ต้องใช้หรือrequire includeฉันพยายามเข้าใจว่าuseคำหลักทำงานอย่างไร ฉันลองทำตามขั้นตอนเหล่านี้แล้ว แต่ไม่มีอะไรทำงาน:

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

มันบอกว่า:

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

คำหลักuseทำงานอย่างไร ฉันสามารถใช้มันเพื่อนำเข้าคลาสได้หรือไม่


1
คุณไม่สามารถทำได้โดยไม่ต้องนำเข้าไฟล์ กรุณาอย่าเปลี่ยนการไหล นอกจากนี้เนมสเปซไม่ได้ใช้ใน PHP จริงๆ เช่นเดียวกับ VB.NET
Cole Johnson

13
@ cole-johnson ไม่เห็นด้วยกับคุณ Symfony ถูกสร้างขึ้นรอบnamespaces ในความเป็นจริงไม่มี Symfony ใด ๆ หากคุณไม่ใช้ namespaces
Green

คำตอบ:


80

useไม่รวมอะไรเลย มันเพียงนำเข้าเนมสเปซที่ระบุ (หรือคลาส) ไปยังขอบเขตปัจจุบัน

หากคุณต้องการให้คลาสมีการโหลดอัตโนมัติ - อ่านเกี่ยวกับการโหลดอัตโนมัติ


@ G-Man มันตอบคำถามที่ถามมาก
zerkms

188

ไม่คุณไม่สามารถนำเข้าชั้นเรียนด้วยuseคำหลัก คุณต้องใช้include/ requireคำสั่ง แม้ว่าคุณจะใช้ PHP โหลดเดอร์อัตโนมัติ แต่ออโต้โหลดเดอร์ก็ยังต้องใช้อย่างใดอย่างหนึ่งincludeหรือrequireภายใน

วัตถุประสงค์ของการใช้คำสำคัญ:

พิจารณากรณีที่คุณมีสองคลาสที่มีชื่อเดียวกัน คุณจะพบว่ามันแปลก แต่เมื่อคุณทำงานกับโครงสร้าง MVC ขนาดใหญ่มันจะเกิดขึ้น ดังนั้นถ้าคุณมีสองคลาสที่มีชื่อเหมือนกันให้ใส่ไว้ในเนมสเปซที่ต่างกัน ตอนนี้ให้พิจารณาว่าตัวโหลดอัตโนมัติของคุณกำลังโหลดทั้งสองคลาส (ทำโดยrequire) และคุณกำลังจะใช้อ็อบเจกต์ของคลาส ในกรณีนี้คอมไพเลอร์จะสับสนว่าคลาสอ็อบเจ็กต์ใดที่โหลดระหว่างสอง เพื่อช่วยให้คอมไพเลอร์ตัดสินใจคุณสามารถใช้useคำสั่งเพื่อให้สามารถตัดสินใจได้ว่าจะใช้คำสั่งใด

กรอบการทำงานที่สำคัญในปัจจุบันใช้includeหรือrequireผ่านcomposerและpsr

1) นักแต่งเพลง

2) ระบบโหลดอัตโนมัติPSR-4

ผ่านพวกเขาอาจช่วยให้คุณเพิ่มเติม คุณยังสามารถใช้นามแฝงเพื่อระบุคลาสที่แน่นอน สมมติว่าคุณมีสองคลาสที่มีชื่อเหมือนกันพูดMailerด้วยสองเนมสเปซที่แตกต่างกัน:

namespace SMTP;
class Mailer{}

และ

namespace Mailgun;
class Mailer{}

และถ้าคุณต้องการใช้คลาส Mailer ทั้งสองในเวลาเดียวกันคุณสามารถใช้นามแฝงได้

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

ในภายหลังในรหัสของคุณหากคุณต้องการเข้าถึงวัตถุคลาสเหล่านั้นคุณสามารถทำสิ่งต่อไปนี้:

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

มันจะอ้างอิงระดับเดิม

บางคนอาจสับสนว่าไม่มีชื่อคลาสที่คล้ายกันดังนั้นจึงไม่มีการใช้useคำหลัก คุณสามารถใช้__autoload($class)ฟังก์ชั่นซึ่งจะถูกเรียกโดยอัตโนมัติเมื่อuseคำสั่งถูกเรียกใช้กับคลาสเพื่อใช้เป็นอาร์กิวเมนต์และสามารถช่วยให้คุณโหลดคลาสในขณะทำงานได้ทันทีตามต้องการ

อ้างอิงคำตอบนี้เพื่อทราบข้อมูลเพิ่มเติมเกี่ยวกับออโต้โหลดระดับ


ทำไมไม่ใช้ชื่อคลาสอื่น
ศักดิ์สิทธิ์

15
@divine ชั้นเรียนอาจมาจากผู้ขายบุคคลที่สาม
Dayo

3
@divine เกิดอะไรขึ้นถ้าทั้งสองคลาสที่มาจากบุคคลที่สาม?
Dayo

2
@divine ตามแบบแผนเนมสเปซจะเป็น <vendorName> / <packageName> เพื่อให้วิธีการนี้ได้รับการแก้ไขแล้ว การประชุมต่อไปนี้เป็นไปไม่ได้ที่ผู้บรรจุหีบห่อจะยอมรับชื่อผู้ขายรายเดียวกันจากบุคคลอื่น และ packagist.org เป็นที่เก็บ PHP ที่ใช้สำหรับการติดตั้งนักแต่งเพลงของแพ็คเกจ
Tpojka

1
@root ไม่สำคัญแค่บอกเวลารันไทม์ว่าจะใช้อะไร เหมือนว่าคุณกำลังขับรถยนต์และมีสัญญาณบอกคุณล่วงหน้าและคุณแตกสลายเหมือนuseคำสั่งที่จะบอกคอมไพเลอร์โหลดสิ่งนี้ให้ฉันตอนนี้ เข้าใจแล้ว!
Rajan Rawal

23

อย่าคิดว่าNamespaceคืออะไร

โดยปกติแล้วNamespaceนั้นเป็นเพียงคำนำหน้าคลาส (เช่นไดเรกทอรีในระบบปฏิบัติการ) เพื่อให้แน่ใจว่ามีเอกลักษณ์ของเส้นทางของคลาส

นอกจากนี้เพื่อให้สิ่งต่าง ๆ ชัดเจนคำสั่งการใช้งานไม่ได้ทำอะไรเพียงนามแฝงNamespacesของคุณเพื่อให้คุณสามารถใช้ทางลัดหรือรวมClassesด้วยชื่อเดียวกัน แต่Namespaceต่าง ๆในไฟล์เดียวกัน

เช่น:

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

หากคุณต้องการทราบว่า PHP Namespaces และการโหลดอัตโนมัติ (แบบเก่าและวิธีใหม่กับ Composer) ทำงานอย่างไรคุณสามารถอ่านโพสต์บล็อกที่ฉันเพิ่งเขียนในหัวข้อนี้: https://enterprise-level-php.com/ 2017/12 / 25 / the-มายากลเบื้องหลัง autoloading-PHP ไฟล์โดยใช้-composer.html


8

คุณจะต้องรวม / ต้องการคลาสมิฉะนั้น PHP จะไม่ทราบเกี่ยวกับเนมสเปซ
คุณไม่จำเป็นต้องทำในไฟล์เดียวกัน คุณสามารถทำได้ในไฟล์ bootstrap เช่น (หรือใช้ตัวโหลดอัตโนมัติ แต่ไม่ใช่หัวข้อจริง)


4

ปัญหาน่าจะเกิดขึ้นมากที่สุดที่คุณจะต้องใช้ตัวโหลดอัตโนมัติที่จะใช้ชื่อคลาส (แยกโดย '\' ในกรณีนี้) และแมปกับโครงสร้างไดเรกทอรี

คุณสามารถตรวจสอบบทความนี้ในฟังก์ชั่นการโหลดอัตโนมัติของ PHP มีฟังก์ชั่นการใช้งานหลายประเภทในกรอบงานนี้อยู่แล้ว

ฉันใช้งานจริงมาก่อน นี่คือการเชื่อมโยง


มีปัญหากับมันว่า มันต้องการโมเดลแบบเรียกซ้ำเพื่อให้สร้างเส้นทางแบบเต็ม ตอนนี้จัดการกับเนมสเปซระดับเดียวเท่านั้น
Tyler Carter

3

ฉันเห็นด้วยกับสีเขียว Symfony ต้องการเนมสเปซดังนั้นทำไมไม่ใช้มัน

นี่คือวิธีที่คลาสตัวควบคุมตัวอย่างเริ่มต้น:

เนมสเปซ Acme \ DemoBundle \ Controller;

ใช้ Symfony \ Bundle \ FrameworkBundle \ Controller \ Controller;

คลาส WelcomeController ขยายคอนโทรลเลอร์ {... }


3

ฉันสามารถใช้มันเพื่อนำเข้าคลาสได้หรือไม่

คุณไม่สามารถทำเช่นนั้นได้นอกเหนือจากตัวอย่างด้านบน คุณยังสามารถใช้คำหลักuseในคลาสเพื่อนำเข้าลักษณะเช่นนี้:

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

useคำหลักสำหรับ aliasing ใน PHP และจะไม่นำเข้าชั้นเรียน สิ่งนี้ช่วยได้จริง
1) เมื่อคุณมีคลาสที่มีชื่อเหมือนกันในเนมสเปซที่ต่างกัน
2) หลีกเลี่ยงการใช้ชื่อคลาสที่ยาวมาก ๆ ซ้ำแล้วซ้ำอีก


2

Namespace ใช้เพื่อกำหนดพา ธ ไปยังไฟล์เฉพาะที่มีคลาสเช่น

namespace album/className; 

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

จากนั้นคุณสามารถรวมคลาสที่เฉพาะเจาะจงนี้ลงในไฟล์ php อื่นโดยใช้คำหลัก "ใช้" เช่นนี้:

use album/className;

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

หมายเหตุ: อย่าใช้พา ธ ไปยังไฟล์ที่มีคลาสที่จะนำไปใช้ขยายขอบเขตการใช้เพื่อสร้างอินสแตนซ์ของวัตถุ แต่ใช้เฉพาะเนมสเปซ


2

การใช้คำสำคัญ "use" ใช้สำหรับย่อตัวอักษรเนมสเปซ คุณสามารถใช้ทั้งกับ aliasing และไม่ใช้ก็ได้ หากไม่มีนามแฝงคุณต้องใช้ส่วนสุดท้ายของเนมสเปซแบบเต็ม

<?php
    use foo\bar\lastPart;
    $obj=new lastPart\AnyClass(); //If there's not the line above, a fatal error will be encountered.
?>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.