что такое пространство имен php
Что такое пространство имен php
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Хотя любой корректный PHP-код может находиться внутри пространства имён, только классы (включая абстрактные и трейты), интерфейсы, функции и константы зависят от него.
Пример #1 Объявление единого пространства имён
Замечание: Абсолютные имена (т.е. имена, начинающиеся с обратной косой черты) не допускаются в объявлениях пространства имён, поскольку такие конструкции интерпретируются как относительные выражения пространства имён.
Пример #2 Объявление простого пространства имён
Кроме того, в отличие от любой другой конструкции PHP, одно и то же пространство имён можно определять в нескольких файлах, что позволяет распределять их содержимое по файловой системе.
User Contributed Notes 9 notes
If your code looks like this:
namespace NS ;
?>
. and you still get «Namespace declaration statement has to be the very first statement in the script» Fatal error, then you probably use UTF-8 encoding (which is good) with Byte Order Mark, aka BOM (which is bad). Try to convert your files to «UTF-8 without BOM», and it should be ok.
Regarding constants defined with define() inside namespaces.
define() will define constants exactly as specified. So, if you want to define a constant in a namespace, you will need to specify the namespace in your call to define(), even if you’re calling define() from within a namespace. The following examples will make it clear.
The following code will define the constant «MESSAGE» in the global namespace (i.e. «\MESSAGE»).
Expanding on @danbettles note, it is better to always be explicit about which constant to use.
echo foo ; // 111.
echo \ foo ; // 222.
echo \ NS \ foo // 111.
echo NS \ foo // fatal error. assumes \NS\NS\foo.
?>
«A file containing a namespace must declare the namespace at the top of the file before any other code»
It might be obvious, but this means that you *can* include comments and white spaces before the namespace keyword.
// Lots
// of
// interesting
// comments and white space
namespace Foo ;
class Bar <
>
?>
You should not try to create namespaces that use PHP keywords. These will cause parse errors.
namespace Project / Classes /Function; // Causes parse errors
namespace Project /Abstract/ Factory ; // Causes parse errors
?>
Что такое пространство имен php
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Ниже приведён пример трёх вариантов синтаксиса в реальном коде:
namespace Foo \ Bar \ subnamespace ;
const FOO = 1 ;
function foo () <>
class foo
<
static function staticmethod () <>
>
?>
namespace Foo \ Bar ;
include ‘file1.php’ ;
const FOO = 2 ;
function foo () <>
class foo
<
static function staticmethod () <>
>
/* Неполные имена */
foo (); // определяется как функция Foo\Bar\foo
foo :: staticmethod (); // определяется как класс Foo\Bar\foo с методом staticmethod
echo FOO ; // определяется как константа Foo\Bar\FOO
/* Полные имена */
subnamespace \ foo (); // определяется как функция Foo\Bar\subnamespace\foo
subnamespace \ foo :: staticmethod (); // определяется как класс Foo\Bar\subnamespace\foo
// c методом staticmethod
echo subnamespace \ FOO ; // определяется как константа Foo\Bar\subnamespace\FOO
/* Абсолютные имена */
\ Foo \ Bar \ foo (); // определяется как функция Foo\Bar\foo
\ Foo \ Bar \ foo :: staticmethod (); // определяется как класс Foo\Bar\foo с методом staticmethod
echo \ Foo \ Bar \ FOO ; // определяется как константа Foo\Bar\FOO
?>
Пример #1 Доступ к глобальным классам, функциям и константам из пространства имён
function strlen () <>
const INI_ALL = 3 ;
class Exception <>
$a = \ strlen ( ‘hi’ ); // вызывает глобальную функцию strlen
$b = \ INI_ALL ; // получает доступ к глобальной константе INI_ALL
$c = new \ Exception ( ‘error’ ); // Создаёт экземпляр глобального класса Exception
?>
PHP Namespace
Пространство имён (англ. namespace) — некоторое множество, под которым подразумевается модель, абстрактное хранилище или окружение, созданное для логической группировки уникальных идентификаторов (то есть имён). Идентификатор, определенный в пространстве имён, ассоциируется с этим пространством. Один и тот же идентификатор может быть независимо определён в нескольких пространствах. Таким образом, значение, связанное с идентификатором, определённым в одном пространстве имён, может иметь (или не иметь) такое же (а скорее, другое) значение, как и такой же идентификатор, определённый в другом пространстве. Языки с поддержкой пространств имён определяют правила, указывающие, к какому пространству имён принадлежит идентификатор (то есть его определение).wiki
Все ясно? На самом деле все просто. До версии 5.3 в php существовало всего два пространства — глобальное(в котором выполнялся ваш основной код) и локальное(в котором определялись переменные функций).
С версии 5.3 все изменилось. Теперь можно определить свое пространство имен, в котором будут существовать ваши классы методы и т.д.
Надеюсь стало немного понятнее.
Я специально обозвал классы одинаково. Так они определены в разных пространствах, то это два разных класса, несмотря на одинаковые имена. Основной скрипт,-по прежнему, функционирует в глобальном пространстве, здесь ничего не изменилось и в нем, по-прежнему, можно определять классы и функции. Так для чего же тогда нужны пространства? Прежде всего, для уверенности в том, что когда вы подключаете файл, с каким-нибудь фреймворком или библиотекой, ваши классы не переопределят классы фреймворка или наоборот.
Для того, чтобы использовать классы определенные в своем пространстве имен, необходимо в нужном месте(я как правило предпочитаю делать это в начале файла) импортировать определенное вами пространство в глобальное для этого используется ключевое слово
Внимание: по каким-то своим основаниям php не допускает использование ключевого слова use в блоках условий и циклах
возьмем пример с картинок и воплотим его в коде:
Внимание: ключевое слово namespase должно быть расположено в самом начале файла сразу после
Пространства имен в PHP
На хабре можно найти немало статей о пространствах имен в PHP, но мне помогла именно эта, и именно ей я хочу поделится. Наверняка найдутся те, кому этот перевод поможет.
Путь к поддержке пространств имен в PHP был тернистым. Но к счастью она была добавлена к языку в версии PHP 5.3, и структура PHP кода значительно улучшилась с тех пор. Но как именно нам их использовать?
Что такое пространства имен?
«Не забывайте обратный слеш, когда Вы храните имя пространства имен в виде строки!»
Представьте себе пространство имен, как ящик, в который Вы можете положить все что угодно: карандаш, линейку, кусок бумаги и так далее. Это Ваши вещи. Прямо под вашим ящиком, располагается еще чей-то ящик, и его хозяин хранит те же вещи в нем. Чтобы избежать использования предметов друг друга, Вы решили маркировать ящики так чтобы стало ясно, что кому принадлежит.
Ранее разработчикам приходилось использовать префиксы с нижним подчеркиванием в своих классах, функциях и константах для разделения кода. Это эквивалентно тому, что каждый будет маркировать свои вещи и храниться они будут в одном большом ящике. Конечно, это по крайней мере хоть какая-то организации, но это очень неэффективно.
Пространства имен, помогут! Вы можете объявить одни и те же функцию, класс, интерфейс и определить константу в отдельных пространствах имен, не получая фатальных ошибок. По своей сути, пространство имен не более чем иерархически маркированные блоки кода содержащие обычный PHP код.
Вы используете их!
Важно понимать, что Вы косвенно используете пространства имен; Начиная с PHP 5.3, все определения, которые еще не объявлены в определенных пользователем пространствах имен, подпадают под глобальное пространство имен.
Обратите внимание что использование пространства имен не является обязательным.
Ваш PHP скрипт будет прекрасно работать без них, и такое поведение не очень скоро изменится.
Определение пространства имен
Вы можете использовать несколько пространств имен в одном файле.
Вы также можете использовать одно и тоже пространство имен для нескольких разных файлов; процесс подключения файлов автоматически объединит их. Это хорошая практика кодирования, ограничить количество определений пространства имен до одного файла, так же, как Вы могли бы сделать это с классами.
Пространство имен используется, чтобы избежать противоречивых определений и ввести больше гибкости и организации в программный код.
Обратите внимание, что фигурные скобки, совершенно необязательны. На самом деле, используя правило одного пространства имен в одном файле и опуская фигурные скобки Вы делаете ваш код намного чище — нет никакой необходимости, делать отступ(табуляцию) для вложенного кода.
Подпространства имен
Для обеспечения гибкости, разумно хранить вложенные пространства имен в подкаталогах. Это способствует структурированию проекта и позволяет гораздо проще использовать его автозагрузчикам, которые следуют стандарту PSR-4.
PHP использует обратный слэш, в качестве разделителя пространства имен.
Интересный факт: в RFC, чтобы решить, какой разделитель пространства имен следует использовать, рассматривался вариант использования смайлика.
Вы можете использовать столько вложенных пространств имен, сколько хотите.
Определение подпространства имен с вложенными блоками кода не поддерживается. Следующий пример будет возвращать фатальную ошибку: «Объявления пространств имен не могут быть вложенными (Namespace declarations cannot be nested)».
Вызов кода из пространства имен
Если Вы хотите, создать новый экземпляр объекта, вызвать функцию или использовать константы из разных пространств имен, Вы используете обратный слэш. Существует три типа определений имени пространства имен:
Неполное имя
Это имя класса, функции или константы, не включающее в себя ссылку к какому бы то ни было пространству имён. Для тех, кто только начинает работать с пространством имен, это привычная точка зрения.
Полное имя
Так мы получаем доступ к иерархии подпространства имен; разделяется обратным слэшем.
Пример ниже возвратит фатальную ошибку: «Fatal error: Class ‘MyProject\Database\MyProject\FileAccess\Input’ not found», потому что MyProject\FileAccess\Input не имеет отношения к пространству имен в котором Вы находитесь.
Абсолютное имя
Полные и неполные имена используются по отношению к пространству имен в котором Вы находитесь в настоящее время. Они могут быть использованы только для определения доступа на этом уровне или нырять глубже в иерархию пространства имен.
Если Вы хотите получить доступ к функции, классу или константе находящимся на более высоком уровне иерархии, то вам нужно использовать полное имя — абсолютный путь, а не относительный. Вызов должен начинаться с обратного слэша. Это позволяет PHP понять, что этот вызов должен быть осуществлен из глобального пространства, а не обращаться к нему относительно Вашего текущего положения.
Нам не обязательно использовать полное имя для внутренних функций PHP. Неполные имена для функций и констант будут определяться в глобальном пространстве имен, если они не определены в текущем пространстве имен.
Зная это, мы можем теперь перегружать внутренние функции PHP, при этом имея возможность вызвать первоначальную функцию (или константу).
Динамические вызовы
PHP — динамический язык программирования; так что Вы можете применять этот функционал для вызова кода из пространства имён. Это, по существу тоже, что использование динамического имени класса или подключение динамического файла используя переменную для хранения его имени. Разделитель имен PHP использует те же метасимволы в строках. Не забывайте про обратный слеш, когда Вы храните имя пространства имен в виде строки!
Ключевое слово namespace
Ключевое слово namespace используется не только для определения пространства имен, оно также может быть использован для вызова в текущем пространстве имен, функционально аналогичный ключевому слову self для классов.
Константа __NAMESPACE__
Так же как ключевое слово self не может быть использовано для определения имени текущего класса, также и ключевое слово namespace не может использоваться для текущего пространства имен. Поэтому мы используем константу __NAMESPACE__
Эта константа является весьма полезной в начале изучения пространства имен; также она очень полезна при отладке. Так как это строка, она может быть использована в сочетании с динамическими вызовами кода, рассмотренные выше.
Импорт или создание псевдонима имени
не обязательно использовать в пространствах имен
Важная особенность пространств имен в PHP — это возможность ссылаться на внешнее абсолютное имя по псевдониму, или импортирование.
Как это использовать
Абсолютное имя может быть привязаны к более короткому неполному имени, так что вам не придется писать его абсолютное имя каждый раз, когда Вы хотите его использовать. Создание псевдонима или импорт должны происходить в родительском пространстве имен или в глобальном. Попытка сделать это в рамках метода или функции является недопустимым синтаксисом (invalid syntax).
Альтернативой, является возможность присвоения псевдонима с другим именем
Вы также можете импортировать такие глобальные классы, как Exception. При импорте, вам не придется писать его абсолютное имя.
Обратите внимание, что для имен в пространстве имен нет необходимости в начальном обратном слеше и его присутствие там не рекомендуется, так как импортируемые имена должны быть абсолютными и не обрабатываются относительно текущего пространства имен.
Хотя есть поддержка динамического вызова пространства имен, динамический импорт не поддерживается.
Пространства имен в PHP, разъяснение
Прим.пер.: Я в курсе, что на момент перевода актуальная версия PHP — 5.5, а также что есть мудрая книга мануал. Но мне показалось интересным, то как автор преподносит namespace функционал, возможно кому-то из тех, кто только постигает азы (да и не только, есть немало бородатых разработчиков, остановившихся на PHP 5.2), статья поможет проникнуться. Ходор.
Глобальное пространство имен
Вот такой, очень простой класс:
Ничего особенно, как видите, и если вы хотите использовать его, просто сделайте так:
Хорошо, хорошо, извини. Суть в том, что мы можем думать об этом классе, как находящимся в глобальном пространстве имён.Я не совсем уверен, что это правильный термин, но на мой взгляд это звучит вполне уместно. Собственно, это значит то, что класс не принадлежит никакому пакету, просто обычный класс.
Простое использование пространств имён
Давайте создадим еще одного Эддарда, рядом с тем, глобальным.
Здесь у нас очень похожий класс с одним небольшим изменением, добавлена директива пространства имен. Строка namespace Stark; говорит PHP что мы работаем в пространстве имен Stark и любой код (объявление классов, функций, переменных и т.д.) будет относиться к нему.
Итак, нам нужно создать нового Эдда, если вы решили что это нужно сделать вот так:
То нет, это не так. Здесь мы получаем экземпляр класса из первого примера, который мы создали ранее. Не тот, в пространстве имен Stark. Давайте попробуем создать экземпляр Эддарда Старка.
Для создания экземпляра класса нам нужно предварить имя класса префиксом из названия пространства имен, которому класс принадлежит, а в качестве разделителя использовать обратную косую черту. В итоге у нас есть экземпляр именно того класса, что нам нужен. Разве это не волшебно?
К слову сказать, пространства имён могут образовывать сколь угодно сложную иерархию, используя столько уровней, сколько потребуется. Например:
Теория относительности
Помните, как я сказал вам, что PHP всегда работает относительно текущего пространства имен. Давайте взглянем на это в действии:
Добавив директиву пространства имён, мы дали понять PHP, что мы находимся в пространстве имён Stark. Так как именно в нем мы определили класс Eddard, то именно его мы и получим. Видите — все относительно.
Сейчас, когда мы изменили пространство имён, у нас возникла одна маленькая проблема. Есть идеи, о чем я? А как нам теперь получить наш оригинальный класс Eddard? Ну тот, который в глобальном пространстве?
К счастью в PHP есть трюк, который позволит нам решить эту проблему — просто добавив \ к имени класса.
Видя ведущий слеш PHP понимает, что нужно выглянуть за пределы текущего namespace и создает экземпляр нужного нам класса.
А сейчас включи свое воображение. Представь, что у нас есть класс из другого пространства имен, названный Tully\Edmure. Сейчас нам нужно использовать его внутри пространства Stark. И как нам это сделать?
И снова нам пришлось использовать обратный слеш, чтобы перейти к глобальной видимости, прежде чем создать экземпляр класса в пространстве Tully.
Вообще, ссылаться вот так на классы из других пространств имен, используя полную иерархию в названии, может быть довольно утомительно. Но к счастью, есть возможность сделать ярлык, давайте посмотрим:
А, еще один маленький трюк! Мы можем дать нашим импортируемым классам прозвища:
Давая Daenerys из пространства Dothraki прозвище Khaleesi, мы можем использовать оба класса Daenerys. Довольно удобно, там мы можем использовать все необходимые классы в нашем приложении.
Структура
Пространства имен также могут помочь нам в организации нашего кода. Позвольте, я продемонстрирую.
Скажем, я хочу создать библиотеку с открытым исходным кодом. Мне бы очень хотелось, чтобы другие могли использовать мой код, это было бы здорово! Беда в том, что имена классов в моем коде конфликтовали с собственным приложением пользователя моей библиотеки. Это было бы ужасно неудобно. Вот как я решу эту проблему:
Здесь я использовал свое имя, чтобы показать, что код принадлежит мне, и отделить свой код от кода пользователя моей библиотеки. Внутри базового пространства имен я создал структуру классов в соответствии с их иерархией.
Начав использовать composer, вы узнаете, как использовать пространства имён для упрощения автозагрузки кода. Я настоятельно рекомендую вам взглянуть на этот полезный механизм.
Недостатки
По правде говоря, я чувствую себя немного виноватым за то, что назвал этот подзаголовок «Недостатки». То, о чем я собираюсь говорить, на самом деле ошибкой не является.
Дело в том, что в других языках функционал пространств имён реализован похожим образом, и при этом языки обеспечивают дополнительный функционал для взаимодействия с пространствами имён.
В Java, например, вы можете импортировать несколько классов в текущее пространство имен, используя оператор импорта. В Java, import является аналогом use и он использует точки, чтобы отделить вложенные пространства имен (или пакеты). Вот пример:
В PHP у вас так не выйдет. Вы должны импортировать каждый класс в отдельности. Извините. Собственно, почему я извиняюсь? Идите и жалуйтесь команде разработчиков PHP, но я прошу вас — будьте вежливы. Они сделали много интересного в последнее время.
Вот изящный трюк, чтобы немного сгладить озвученную проблему. Представьте себе, что у нас есть структура классов из предыдущего примера. Мы можем взять часть подпространства и дать ему псевдоним.
Это может быть полезным при использовании большого числа классов. Добра всем!
Все пожелания и предложения с радостью приму в личку, спасибо.