Как работает ключевое слово «use» в 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
Коул Джонсон

14
@ Коул-Джонсон, не согласен с тобой. Symfony построен вокруг namespaces. На самом деле Symfony не существует, если вы не используете пространства имен
Green

Ответы:


80

useничего не включает Он просто импортирует указанное пространство имен (или класс) в текущую область

Если вы хотите, чтобы классы загружались автоматически - читайте об автозагрузке


@ G-Man отвечает на самые заданные вопросы.
zerkms

188

Нет, вы не можете импортировать класс с useключевым словом. Вы должны использовать include/ requireзаявление. Даже если вы используете автозагрузчик PHP, автозагрузчик все равно придется использовать либо внутри, includeлибо requireвнутри.

Цель использования ключевого слова:

Рассмотрим случай, когда у вас есть два класса с одинаковым именем; Вы найдете это странным, но когда вы работаете с большой структурой MVC, это случается. Поэтому, если у вас есть два класса с одинаковыми именами, поместите их в разные пространства имен. Теперь рассмотрим, когда ваш автозагрузчик загружает оба класса (делает by require), и вы собираетесь использовать объект класса. В этом случае компилятор запутается, какой объект класса загружать среди двух. Чтобы помочь компилятору принять решение, вы можете использовать этот useоператор, чтобы он мог принять решение о том, какой из них будет использоваться.

В настоящее время основные структуры используют includeили requireчерез composerиpsr

1) композитор

2) ПСР-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. Что, если оба сталкивающихся класса от третьих лиц?
Дайо

2
@divine По соглашению, пространство имен будет <vendorName> / <packageName>, так что это уже было решено. В соответствии с соглашением, упаковщик не может принять то же имя поставщика от кого-либо еще. И packagist.org - это PHP-репозиторий, который используется для установки пакетов компоновщиком.
Тпойка

1
@root не имеет значения, он просто говорит во время выполнения, что нужно использовать. как будто вы едете на машине, а сигнал указывает на то, что вы натолкнетесь вперед, а вы сломаетесь, как в случае, когда useоператор way покажет, что компилятор загрузит это для меня сейчас. Дорогая!
Раджан Равал

23

Не задумывайтесь над тем, что такое пространство имен .

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

Также, чтобы прояснить ситуацию, оператор use ничего не делает, только накладывая псевдонимы на свои пространства имен, поэтому вы можете использовать ярлыки или включать классы с тем же именем, но с другим пространством имен в один и тот же файл.

Например:

// 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 и автозагрузка (как по старому, так и по-новому с Composer), вы можете прочитать сообщение в блоге, которое я только что написал по этой теме: https://enterprise-level-php.com/ 2017/12 / 25 /-магия-за-самозарядных-PHP-файлов, используя-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», например:

use album/className;

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

ПРИМЕЧАНИЕ. Не используйте путь к файлу, содержащему класс, который должен быть реализован, расширяет область применения для создания экземпляра объекта, но используйте только пространство имен.


2

Использование ключевого слова «use» для сокращения литералов пространства имен. Вы можете использовать как с псевдонимами, так и без него. Без псевдонимов вы должны использовать последнюю часть полного пространства имен.

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