Использование пространств имен: импорт/создание псевдонима имени
Возможность ссылаться на внешнее абсолютное имя по псевдониму или импортирование — это важная особенность пространств имен. Это похоже на возможность файловых систем unix создавать символические ссылки на файл или директорию.
Все версии PHP, поддерживающие пространства имен, поддерживают три вида создания псевдонима имени или импорта: создание псевдонима для имени класса, создание псевдонима для имени интерфейса и для имени пространства имен. PHP 5.6+ также поддерживает импорт функций и имен констант.
В PHP создание псевдонима имени выполняется с помощью оператора use. Вот пример, показывающий 5 типов импорта:
Пример #1 импорт/создание псевдонима имени с помощью оператора use
namespace foo ;
use My \ Full \ Classname as Another ;
?php
// это тоже самое, что и использование My\Full\NSname как NSname
use My \ Full \ NSname ;
// импортирование глобального класса
use ArrayObject ;
// импортирование функции (PHP 5.6+)
use function My \ Full \ functionName ;
// псевдоним функции (PHP 5.6+)
use function My \ Full \ functionName as func ;
// импортирование константы (PHP 5.6+)
use const My \ Full \ CONSTANT ;
$obj = new namespace\ Another ; // создает экземпляр класса foo\Another
$obj = new Another ; // создает объект класса My\Full\Classname
NSname \ subns \ func (); // вызывает функцию My\Full\NSname\subns\func
$a = new ArrayObject (array( 1 )); // создает объект класса ArrayObject
// без выражения «use ArrayObject» мы создадим объект класса foo\ArrayObject
func (); // вызывает функцию My\Full\functionName
echo CONSTANT ; // выводит содержимое константы My\Full\CONSTANT
?>
Обратите внимание, что для имен в пространстве имен (абсолютные имена, содержащие разделитель пространств имен, такие как Foo\Bar, в отличие от глобальных имен, которые его не содержат, такие как FooBar) нет необходимости в начальном обратном слеше (\) и его присутствие там не рекомендуется, так как импортируемые имена должны быть абсолютными и не обрабатываются относительно текущего пространства имен.
PHP дополнительно поддерживает удобное сокращение для задания нескольких операторов use в одной и той же строке
Пример #2 импорт/создание псевдонима имени с помощью оператора use, комбинирование нескольких операторов use
use My \ Full \ Classname as Another , My \ Full \ NSname ;
?php
$obj = new Another ; // создает объект класса My\Full\Classname
NSname \ subns \ func (); // вызывает функцию My\Full\NSname\subns\func
?>
Импорт выполняется во время компиляции, и не влияет на имена динамических классов, функций или констант.
Пример #3 Импорт и динамические имена
use My \ Full \ Classname as Another , My \ Full \ NSname ;
?php
$obj = new Another ; // создает объект класса My\Full\Classname
$a = ‘Another’ ;
$obj = new $a ; // создает объект класса Another
?>
В дополнение, импорт распространяется только на неполные и полные имена. Абсолютные имена не затрагиваются операцией импорта.
Пример #4 Импортирование и абсолютные имена
use My \ Full \ Classname as Another , My \ Full \ NSname ;
?php
$obj = new Another ; // создает объект класса My\Full\Classname
$obj = new \ Another ; // создает объект класса Another
$obj = new Another \ thing ; // создает объект класса My\Full\Classname\thing
$obj = new \ Another \ thing ; // создает объект класса Another\thing
?>
Scoping rules for importing
Ключевое слово use должно быть указано в самом начале файла (в глобальной области) или внутри объявления пространства имен. Это необходимо потому, что импорт выполняется во время компиляции, а не во время исполнения, поэтому оно не может быть заключено в блок. Следующий пример показывает недопустимое применение ключевого слова use:
Пример #5 Недопустимое правило импорта
class Greenlandic
use Languages \ Danish ;
Замечание:
Правила импорта задаются на каждый файл отдельно. Это означает, что присоединяемые файлы НЕ будут наследовать правила импорта из родительского файла.
Команда use и пространства имен
Пусть также есть класс Page , создающий внутри себя объекты класса Data :
Как вы видите, оба наших класса находятся в совсем разных пространствах имен, поэтому вызовы класса Data упростить нельзя, подобно тому, как мы это делали в предыдущем уроке. Эти вызовы, однако, очень длинные и неудобные, так как в каждом вызове класса Data приходится указывать его длинное пространство имен.
Для решения подобной проблемы существует специальная команда use . С помощью этой команды достаточно один раз подключить класс по его полному имени, и после этого можно будет обращаться к этому классу просто по имени класса. Смотрите пример:
Упростите следующий код с использованием use :
Даны следующие классы:
Упростите код наследования класса, применив команду use .
Подключение нескольких классов
Если нужно подключить несколько классов, то каждый из них подключается своей командой use :
Упростите следующий код с использованием use :
Команда use и относительные пути
При использовании команды use можно указывать относительные пути, подобно тому, как мы это делали в предыдущем уроке. Давайте посмотрим на примере. Пусть мы подключаем некоторый класс:
Как вы видите, начало пространства имен подключаемого класса совпадает с текущим пространством. Это значит, что мы можем эту часть при подключении нашего класса, убрав при этом начальный обратный слеш:
Упростите следующий код с использованием use :
Use php как использовать
Пространства имен позволяют избежать конфликта имен и сгруппировать функционал. Внутри пространства имен могут быть размещены классы, интерфейсы, функции и константы.
Если какая-та конструкция (например, класс или функция) определена вне любого пространства имен, то считается, что она расположена в глобальном пространстве имен.
Определение пространства имен
Для создания пространства имен применяется директива namespace , после которой идет название пространства имен:
namespace base; class Person < private $name; function __construct($name) < $this->name = $name; > >
В данном случае определено пространство имен «base». Обычно названия пространств указываются в нижнем регистре. Все, что расположено ниже этой директивы, относится к пространству имен «base». То есть класс Person принадлежит пространству имен base.
Стоит учитывать, что определение пространства имен должно быть расположено выше любого другого кода или разметки html. Например:
name = $name; > > ?>METANIT.COM name; ?>
Обращение к пространству имен
Для обращения к конструкциям из пространства имен перед названием конструкции через слеш указывается ее пространство имен. Например, у нас есть файл Person.php :
name = $name; > > ?>
Теперь в другом файле подключим этот файл и обратимся к классу Person:
name; ?>
Здесь определено другое пространство имен — «work». Сначала в нем подключается файл «Person.php». Затем создаем объект класса Person.
Если конструкции одного пространства имен используются в другом пространстве имен (в том числе в глобальном пространстве имен), то перед названием конструкции указывается название ее пространства имен. Так, поскольку класс Person расположен в другом пространстве имен — «base», то перед названием класса указываем его полное имя с учетом его пространства имен:
$tom = new \base\Person("Tom");
Обратите внимание, что сначала идет слеш, потом название пространства имен и потом через слеш название класса ( \base\Person ).
Без указания пространства имен мы можем использовать конструкцию только в том же пространстве имен, в котором она определена.
Вложенные пространства имен
Одни пространства имен могут содержать другие. Например:
name = $name; > > ?>
Здесь класс Person определен в пространстве имен base\classes\ . То есть теперь для обращения к классу Person в другом пространстве имен надо указывать \base\classes\Person :
name; ?>
Псевдонимы
Если в одном пространстве имен используется какой-то класс из другого пространства имен, то писать каждый раз полное имя класса с учетом его пространства имен может быть утомительно, кроме того, перегружает код. Например:
name . "
"; $bob = new \base\classes\Person("Bob"); echo $bob->name; ?>
В этом случае мы можем использовать псевдонимы, которые задаются в виде
use полное_имя_класса as псевдоним;
Конструкция use импортирует класс из другого пространства имен, а оператор as устанавливает для него псевдоним.
Так, сократим предыдущий код с помощью псевдонимов:
name . "
"; $bob = new User("Bob"); echo $bob->name; ?>
В данном случае для класса \base\classes\Person установлен псевдоним User , соответственно теперь для обращения к классу Person мы можем использовать его псевдоним User. Результат тот же, но кода меньше.
Можно использовать только конструкцию use без указания псевдонима. Тогда класс можно будет исользовать по его непосредственному имени:
name . "
"; $bob = new Person("Bob"); echo $bob->name; ?>
Подключение множества классов
Подобным образом можно подключать сразу несколько классов. Например, пусть в файле Person.php имеются следующие классы:
name = $name; > > class Employee extends Person < >?>
Подключение классов Person и Employee:
name . "
"; $sam = new Employee("Sam"); echo $sam->name; ?>
Определение псевдонимов можно сократить:
use \base\classes\;
Подключение констант и функций
Для подключения констант применяется инструкция use const , а для подключения функций — use function .
Например, определение файла Person.php :
name . "
"; > class Person < public $name; function __construct($name) < $this->name = $name; > > ?>
Подключим класс Person вместе с константой adminName и функцией printPerson:
В чем разница между namespace и use? И как они связаны с файловой системой?
Здравствуйте. Изучаю php, дошел до классов и пространств имен.
Сразу скажу, что изучая php я и читаю мануал, но я так и не понял, как задавать пространства имен, как они связаны с файловой системой, в чем разница между use и namespace?
www.php-fig.org/psr/psr-4 не прояснил ситуацию, а еще больше её усугубил.
Я понимаю, что вопрос скорей всего очень глупый, поэтому очень прошу отнестись с терпением и пониманием :).
Заранее благодарен всем отозвавшимся.
- Вопрос задан более трёх лет назад
- 4600 просмотров
Комментировать
Решения вопроса 2
попытаюсь более человечнее написать =)
с файловой системой ни то ни другое никак не связаны. Просто приняли так, чтобы путь совпадал с namespace’ом, стандартизировали короче для удобства. Ну и свои плюсы имеются конечно же.
namespace это установка пространства имен. Скажем так — виртуальная коробочка, в которой лежат всякие штуки (классы). Это дает возможность использовать одинаковые названия классов для одного приложения.
use указывает какой класс из какого пространства имен использовать. Его можно не писать, но тогда придется вызывать классы вместе с их namespace (если у тех классов они заданы, если нет, то все равно надо указывать глобальное пространство «\»).
типа: $customers = new \app\models\Customers();
В мануале все четко расписано в принципе, читай и пытайся понять =)
Ответ написан более трёх лет назад
Комментировать
Нравится 5 Комментировать
Иван Корюков @MadridianFox
Web-программист, многостаночник
На уровне языка пространства имён с файловой системой никак не связаны.
Пространства имён — лишь способ решить конфликты имён классов.
Вот ты говоришь — у меня есть класс ClassName, но к сожалению, такой класс уже есть в одной из библиотек, которые ты используешь. Можно было бы назвать класс MyClassName, ну и везде добавлять приставку My. Редко, но бывает что надо сделать два класса с одинаковым именем в одном проекте. Тогда ты называешь один класс MyBananaSybsystemClassName, а другой MyAnanasSubsystemClassName — тем самым обозначая разницу в названии.
И даже это не спасёт от простого совпадения.
И тут на помощь приходят пространства имён.
В начале файла в котором лежат классы (лучше один класс в одном файле) пишется название пространсва имён, вот так:
namespace banana;
И теперь все классы, объявленные в этом пространстве имён имеют название banana\ClassName, хотя внутри этого файлв ты можешь по прежнему обращаться к ним просто по ClassName.
В другом файле надо использовать полное название, вроде как:
$obj = new banana\ClassName();
но, если надо много раз писать название класса можно сделать вот так:
use banana\ClassName; $obj = new ClassName();
, но самое полезное здесь это разрешение конфликтов. Если вдруг в другом месте определён такой же ClassName, то можно просто переименовать его:
use banana\ClassName; use ananas\ClassName as AnanasClass; $obj1 = new ClassName(); $obj2 = new AnanasClass();
Вот это и есть суть пространства имён. Таковы они во всех языках программирования в которых они есть.
Но есть от них ещё одна польза — можно настроить автоматическое подключение unclude(); файла с классом.
Делается это с помощью определения функции автозагрузки
function __autoload($classname) < // как-то по имени класса находим файл и подключаем >// или, лучше spl_autoload_register(function ($classname) < // как-то по имени класса находим файл и подключаем >);
Каждый раз, когда ты обращаешься к классу и php не может его найти в подключенных файлах — запускается код написанный в функции автозагрузки. В эту функцию передаётся название класса.
При чём же тут пространства имён? А при том, что в функцию автозагрузки передаётся полное имя класса с пространтсвом имён.
Это значит что ты можешь делать по одному файлу на класс, класть их в папки, а в пространство имён в каждом файле писать путь до этого файла.
После этого пишешь функцию, которая просто заменяет в названии класса слеши на те, что поддерживаются операционной системой как разделители пути, и просто подключаешь файл.
Именно об этом и написано в каком-то там PSR