Як ключове слово "використовувати" працює в PHP і чи можу я імпортувати з ним класи?


136

У мене є файл з класом Resp. Шлях:

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

І я маю index.phpфайл у цьому каталозі:

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

У цьому index.phpфайлі я хочу інстанціювати клас Resp.

$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
Коул Джонсон

13
@ cole-johnson, не згоден з тобою. Symfony побудований навколо namespaces. Насправді немає Symfony, якщо ви не використовуєте простору імен
Зелений

Відповіді:


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. Заняття можуть бути від сторонніх постачальників
Дайо

3
@divine. Що робити, якщо обидва класи стикаються від третіх сторін?
Дайо

2
@divine За умовою, простір імен буде <vendorName> / <packageName>, так що це вже вирішено. Після домовленостей упаковщику неможливо прийняти те саме ім’я постачальника від когось іншого. І packgist.org - це сховище PHP, яке використовується для композиторської установки пакетів.
Tpojka

1
@root не має значення, він просто повідомляє час запуску, що потрібно використовувати. як ти за кермом автомобіля, і сигнал каже тобі наперед і ти зламаєшся, як useзаява способу скаже компілятору завантажити це для мене зараз. Зрозумів, дорогий!
Раджан Равал

23

Не передумуйте, що таке простір імен .

Простір імен - це лише префікс класу (наприклад, каталог в операційній системі) для забезпечення класу унікальності шляху .

Крім того, щоб зрозуміти все, оператор використання не робить нічого лише псевдонімом ваших просторів імен, тому ви можете використовувати ярлики або включати класи з тим самим іменем, але різні області імен в одному файлі.

Наприклад:

// 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 Namespace and autoloading (старий спосіб, а також новий спосіб із Composer), ви можете прочитати повідомлення в блозі, який я щойно писав на цю тему: https://enterprise-level-php.com/ 2017/12/25 / the-magic-поза-автозавантаження-php-файлів-using-composer.html


8

Вам доведеться все-таки включити / вимагати клас, інакше PHP не дізнається про область імен.
Не потрібно робити це в одному файлі. Наприклад, це можна зробити у файлі завантаження. (або використовувати автозавантажувач, але це не тема насправді)


4

Проблема, швидше за все, вам потрібно буде використовувати автоматичний завантажувач, який буде приймати ім'я класу (у цьому випадку перервати на '\') та відобразити його в структурі каталогу.

Ви можете ознайомитися з цією статтею про функцію автоматичного завантаження PHP. В рамках уже існує багато реалізацій цього типу функціональності.

Я фактично реалізував її раніше. Ось посилання .


Однак з цим є проблема. Потрібна рекурсивна модель, яка дозволить їй створити повний шлях. Зараз він обробляє лише однорівневі простори імен.
Тайлер Картер

3

Я погоджуюся з Green, 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Ключове слово для накладення на PHP і не імпортувати класи. Це дійсно допомагає
1) Якщо у вас є класи з однаковою назвою в різних просторах імен.
2) Не використовуйте справді довге ім'я класу знову і знову.


2

Простір імен використовується для визначення шляху до певного файлу, що містить клас, наприклад

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

Використання ключового слова "використання" призначене для скорочення простору імен. Ви можете використовувати як з псевдонімом, так і без нього. Не створюючи довільне використання, ви повинні використовувати останню частину повного простору імен.

<?php
    use foo\bar\lastPart;
    $obj=new lastPart\AnyClass(); //If there's not the line above, a fatal error will be encountered.
?>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.