Пространство имен PHP (пространство имен) было добавлено в PHP 5.3. Если вы изучали C# и Java, в пространстве имен нет ничего нового. Тем не менее, он по-прежнему имеет очень важное значение в PHP.
Пространства имен PHP могут решить следующие два типа проблем:
Конфликты имен между написанным пользователем кодом и внутренними классами/функциями/константами PHP или сторонними классами/функциями/константами.
Создайте псевдоним (или короткое) имя для очень длинного имени-идентификатора (обычно определяемого для устранения проблем первого типа), чтобы улучшить читаемость исходного кода.
По умолчанию все имена констант, классов и функций размещаются в глобальном пространстве, как и раньше, когда PHP поддерживал пространства имен.
Пространства имен объявляются с использованием ключевого слова namespace. Если файл содержит пространство имен, он должен объявить это пространство перед всем остальным кодом. Формат синтаксиса следующий:
<?php // Определить код в пространстве имен MyProject namespace MyProject; // ... код...
Вы также можете определить разные коды пространства имен в одном файле, например:
<?php namespace MyProject;const CONNECT_OK = 1;class Connection { /* ... */ }function Connect() { /* ... */ }namespace AnotherProject;const CONNECT_OK = 1;class Connection { /* .. . */ } function Connect() { /* ... */ }?>
Не рекомендуется использовать этот синтаксис для определения нескольких пространств имен в одном файле. Рекомендуется использовать следующую форму синтаксиса фигурных скобок.
<?phpnamespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function Connect() { /* ... */ }} namespace AnotherProject { const CONNECT_OK = 1; class Connection { /* .. . */ } function Connect() { /* ... */ }}?>
Чтобы объединить глобальный код, не относящийся к пространству имен, с кодом пространства имен, можно использовать только синтаксис фигурных скобок. Глобальный код должен быть заключен в безымянный оператор пространства имен, за которым следуют фигурные скобки, например:
<?phpnamespace MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function Connect() { /* ... */ }}namespace { // Глобальный код session_start();$a = MyProject Connect();echo MyProjectConnection::start();}?>
Единственный допустимый код перед объявлением пространства имен — это оператор объявления, который определяет кодировку исходного файла. Весь код, отличный от PHP, включая пробелы, не может появляться перед объявлением пространства имен.
<?phpdeclare(encoding='UTF-8'); //Определение нескольких пространств имен и пространств имен кода, не включенных в пространство имен MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function Connect () { / * ... */ }}namespace { // Глобальный код session_start();$a = MyProjectconnect();echo MyProjectConnection::start();}?>
Следующий код вызовет синтаксическую ошибку:
<html><?phpnamespace MyProject; // появление «<html>» перед пространством имен приведет к фатальной ошибке — пространство имен должно быть первым оператором сценария программы?>
Подобно взаимоотношениям между каталогами и файлами, пространства имен PHP также позволяют указывать иерархические имена пространств имен. Таким образом, имена пространств имен могут быть определены иерархическим образом:
<?phpnamespace MyProjectSubLevel; //Объявляем единое иерархическое пространство имен const CONNECT_OK = 1;class Connection { /* ... */ }function Connect() { /* ... */ }?>
В приведенном выше примере создается константа MyProjectSubLevelCONNECT_OK, класс MyProjectSubLevelConnection и функция MyProjectSubLevelConnect.
На имена классов в пространстве имен PHP можно ссылаться тремя способами:
Неполное имя или имя класса без префикса, например $a=new foo() или foo::staticmethod();. Если текущим пространством имен является currentnamespace, foo будет разрешено как currentnamespacefoo. Если код, использующий foo, является глобальным и не содержит кода в каком-либо пространстве имен, тогда foo будет разрешен как foo. Предупреждение. Если функция или константа в пространстве имен не определена, неполная функция или имя константы разрешается в глобальную функцию или имя константы.
Полное имя или имя, которое включает префикс, например $a = new subnamespacefoo() или subnamespacefoo::staticmethod();. Если текущим пространством имен является currentnamespace, foo будет разрешено как currentnamespacesubnamespacefoo. Если код, использующий foo, является глобальным, код не содержится ни в одном пространстве имен, foo будет разрешено в subnamespacefoo.
Полное имя или имя, включающее глобальный префиксный оператор, например, $a = new currentnamespacefoo() или currentnamespacefoo::staticmethod();. В этом случае foo всегда разрешается в буквальном имени currentnamespacefoo в коде.
Вот пример использования этих трех методов:
Код файла file1.php
<?phpnamespace FooBarsubnamespace; const FOO = 1; function foo() {}class foo { static function staticmethod() {}}?>
код файла file2.php
<?phpnamespace FooBar;include 'file1.php';const FOO = 2;function foo() {}class foo{ static function staticmethod() {}}/* Неполное имя*/foo(); // Анализируем его это функция FooBarfoofoo::staticmethod(); // Она анализируется в классе FooBarfoo и используется метод staticmethodecho FOO; Разрешает константу FooBarFOO/* квалифицированное имя*/subnamespacefoo() // Разрешает функцию FooBarsubnamespacefoosubnamespacefoo::staticmethod(); // Разрешает класс FooBarsubnamespace; foo, // и методы класса staticmethodecho subnamespaceFOO // преобразуются в константу FooBarsubnamespaceFOO /*; Полное имя */FooBarfoo(); // Разрешается функция FooBarfooFooBarfoo::staticmethod(); // Разрешается класс FooBarfoo и класс Метод staticmethodecho FooBarFOO //Решается как константа FooBarFOO?>
Обратите внимание: для доступа к любому глобальному классу, функции или константе вы можете использовать полное имя, например strlen(), Exception или INI_ALL.
Доступ к глобальным классам, функциям и константам в пространстве имен:
<?phpnamespace Foo;function strlen() {}const INI_ALL = 3;class Exception {}$a = strlen('hi'); // Вызов глобальной функции strlen$b = INI_ALL; // Доступ к глобальной константе INI_ALL$; c = new Exception('error'); // Создаем экземпляр глобального класса Exception?>
На реализацию пространств имен PHP влияет динамическая природа самого языка. Поэтому, если вы хотите преобразовать приведенный ниже код в пространство имен, обращайтесь к элементам динамически.
Код файла example1.php:
<?phpclass classname{ function __construct() { echo __METHOD__,"n" }}function funcname(){ echo __FUNCTION__,"n";}const constname = "global";$a = 'classname';$obj = new $a; // печатаем имя класса::__construct$b = 'funcname';$b(); // печатаем funcnameecho константа('constname'), "n" // печатает глобально?>;
Вы должны использовать полное имя (имя класса, включая префикс пространства имен). Обратите внимание, что обратная косая черта в начале не нужна, поскольку нет разницы между квалифицированными и полными именами в динамических именах классов, именах функций или именах констант.
Динамический доступ к элементам пространства имен
<?phpnamespace namespacename;class classname{ function __construct() { echo __METHOD__,"n" }}function funcname(){ echo __FUNCTION__,"n";}const constname = "namespaced";include 'example1.php'; ;$a = 'classname';$obj = new $a // Выходное имя класса::__construct$b =; 'funcname';$b(); // Имя выходной функции echo константа('constname'), "n" // Глобальный вывод/* Если используются двойные кавычки, метод использования: "\имя_пространства\имя_класса; "* /$a = 'namespacenameclassname';$obj = new $a; // Вывод namespacenameclassname::__construct$a = 'namespacenameclassname';$obj = new $a; // Вывод namespacenameclassname::__construct$b = 'namespacenamefuncname';$b(); // Вывод namespacenamefuncname$b = 'namespacenamefuncname';$b(); // Вывод namespacenamefuncnameecho Constant( 'namespacenameconstname'), "n" // Выходная константа namespacedecho('namespacenameconstname'), "n"; Выходное пространство имен?>
PHP поддерживает два абстрактных метода доступа к элементам в текущем пространстве имен: магическую константу __NAMESPACE__ и ключевое слово namespace.
Значение константы __NAMESPACE__ — это строка, содержащая имя текущего пространства имен. В глобальном коде, не включенном ни в одно пространство имен, он содержит пустую строку.
Пример __NAMESPACE__, код в пространстве имен
<?phpnamespace MyProject;echo '"', __NAMESPACE__, '"' // Вывод "MyProject"?>
__NAMESPACE__ пример, глобальный код
<?phpecho '"', __NAMESPACE__, '"' // Вывод ""?>
Константа __NAMESPACE__ полезна при динамическом создании имен, например:
Создавайте имена динамически, используя __NAMESPACE__
<?phpnamespace MyProject;function get($classname){ $a = __NAMESPACE__ '\' $classname;}?>
Ключевое слово namespace можно использовать для явного доступа к элементам текущего пространства имен или подпространств имен. Это эквивалентно оператору self в классах.
оператор пространства имен, код в пространстве имен
<?phpnamespace MyProject;use blahblah as my; // см. «Использование пространств имен: импорт/создание псевдонимов»blahmine(); // вызывает функцию blahblahmine()namespaceblahmine(); // вызывает функцию MyProjectblahmine()namespacefunc(); // вызывает функцию MyProjectfunc()namespacesubfunc(); MyProjectsubfunc()namespacecname::method(); // вызывает статический метод класса MyProjectcname$a = new namespacesubcname(); // создаёт экземпляр объекта класса MyProjectsub; cname$b = namespaceCONSTANT // присваивает значение константы MyProjectCONSTANT $b?>
оператор пространства имен, глобальный код
<?phpnamespacefunc(); // вызывает функцию func()namespacesubfunc(); // вызывает функцию subfunc()namespacecname::method(); // вызывает статический метод "method"; class cname$a = new namespacesubcname(); // создает экземпляр класса subcname$b = namespaceCONSTANT // присваивает значение константы $b?>
Поддержка пространств имен PHP имеет два способа использования псевдонимов или импорта: использование псевдонимов для имен классов или использование псевдонимов для имен пространств имен.
В PHP псевдонимы реализованы с помощью оператора use. Вот пример использования всех трех возможных методов импорта:
1. Используйте оператор use для импорта/использования псевдонимов.
<?phpnamespace foo;use MyFullClassname as Another;// Следующий пример аналогичен использованию MyFullNSname в качестве NSname use MyFullNSname;// Импортируйте глобальный класс, используя ArrayObject;$obj = новое пространство именAnother; // Создание экземпляра объекта fooAnother $obj = new Another // Создание экземпляра объекта MyFullClassname NSnamesubnsfunc(); Вызов функции MyFullNSnamesubnsfunc$a = new ArrayObject(array(1)); // Создание экземпляра объекта ArrayObject // Если «use ArrayObject» не используется, создайте экземпляр объекта fooArrayObject?>
2. Одна строка содержит несколько операторов использования.
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another // Создание экземпляра объекта MyFullClassname NSnamesubnsfunc(); // Вызов функции MyFullNSname ; субнсфунк?>
Операции импорта выполняются во время компиляции, а динамические имена классов, имена функций или имена констант — нет.
3. Импорт и динамические имена
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another // Создание экземпляра объекта MyFullClassname $a = 'Another';$obj = new $a; Другой объект?>
Кроме того, операция импорта влияет только на неполные и полные имена. Импорт не влияет на полные имена, поскольку они детерминированы.
4. Импортируйте и полные имена.
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another // Создать экземпляр класса MyFullClassname $obj = new Another; // Создать экземпляр другого класса $obj = new Another; вещь; // Создать экземпляр класса MyFullClassnamething $obj = new Anotherthing; // Создать экземпляр класса Anotherthing?>
В пространстве имен, когда PHP встречает неполный класс, функцию или имя константы, он использует другую стратегию приоритета для разрешения имени. Имена классов всегда преобразуются в имена в текущем пространстве имен. Поэтому при доступе к именам классов, которые являются внутренними для системы или не содержатся в пространстве имен, вы должны использовать полное имя, например:
1. Доступ к глобальным классам в пространстве имен
<?phpnamespace ABC;class Exception расширяет Exception {}$a = new Exception('hi'); // $a — объект класса ABCException $b = new Exception( 'hi'); // $b — объект класса Exception $c = new ArrayObject // Неустранимая ошибка, класс ABCArrayObject не найден?>
Для функций и констант, если функция или константа не существует в текущем пространстве имен, PHP вернется к использованию функции или константы в глобальном пространстве.
2. Резервное копирование глобальных функций/констант в пространстве имен.
<?phpnamespace ABC;const E_ERROR = 45;function strlen($str){ return strlen($str) - 1;}echo E_ERROR, "n" // Вывод "45"echo INI_ALL, " n"; // Вывод "7" - использовать глобальную константу INI_ALLecho strlen('hi'), "n"; // Вывод "2"if (is_array('hi')) { // Вывод "не является массивом" echo "является массивомn";} else { echo "не является массивомn";}?>
Если пространство имен не определено, все классы и функции определяются в глобальном пространстве, как и до того, как PHP представил концепцию пространства имен. Префикс к имени указывает на то, что имя находится в глобальном пространстве, даже если оно находится в другом пространстве имен.
Используйте инструкции глобального пространства
<?phpnamespace ABC;/* Эта функция ABCfopen */function fopen() { /* ... */ $f = fopen(...); // Вызов global Функция fopen возвращает $f;} ?>
С момента появления пространств имен наиболее подвержено ошибкам при использовании класса вопрос о том, каков путь поиска этого класса.
<?phpnamespace A;use BD, CE как F; // Вызов функции foo() // Сначала попытаемся вызвать функцию foo(), определенную в пространстве имен "A" // Затем попытаемся вызвать глобальную функцию. function" foo"foo(); // Вызов глобальной пространственной функции "foo" myfoo() // Вызов функции "foo", определенной в пространстве имен "Amy" F(); Сначала попробуйте вызвать функцию «F», определенную в пространстве имен «A» // Затем попробуйте вызвать глобальную функцию «F» // Ссылка на класс new B() // Создать класс «B», определенный в пространстве имен «A» Объект class "AB" new D(); // Если не найден, попробуйте автозагрузить класс "AB" new D() // Используя правила импорта, создайте объект класса "D", определенный в пространстве имен "B"; " // Если не найден. Если найден, попробуйте автоматически загрузить новый класс "BD". F(); // Используя правила импорта, создайте объект класса "E", определенный в пространстве имен "C" // Если он не найден, попробуйте автозагрузить класс "CE" new B(); класса "B", определенного в глобальном пространстве // Если не найден, попытайтесь автозагрузить класс "B" new D() // Создайте объект класса "D", определенный в глобальном пространстве // Если не найден, попробуйте автозарядка класса "Д" новая F(); // Создаем объект класса «F», определенный в глобальном пространстве // Если он не найден, попробуйте автозагрузить класс «F» // Вызов статического метода или функции пространства имен в другом пространстве имен Bfoo(); ; // Вызов функции "foo" в пространстве имен "AB" B::foo() // Вызов метода "foo" класса "B", определенного в пространстве имен "A" // Если класс "AB"; не найдено , затем попытайтесь автоматически загрузить класс "AB" D::foo(); // Используйте правила импорта для вызова метода "foo" класса "D", определенного в пространстве имен "B" // Если класс "BD" " " Если не найден, попробуйте автоматически загрузить класс "BD"Bfoo() // Вызов функции "foo" в пространстве имен "B" B::foo(); функция в глобальном пространстве класса «Б» Метод "foo" // Если класс "B" не найден, попробуйте автозагрузить класс "B" // Статический метод или функция в текущем пространстве имен AB::foo() // Вызов пространства имен "A"; метод "foo" класса "B", определенного в A" // Если класс "AAB" не найден, попробуйте автозагрузить класс "AAB"AB::foo() ; // Вызов метода "foo" класса "B", определенного в пространстве имен "A" // Если класс "AB" не найден, попробуйте автозагрузить класс "AB"?>
Разрешение имен подчиняется следующим правилам:
Вызовы полных имен функций, классов и констант разрешаются во время компиляции. Например, новый AB разрешается в класс AB .
Все неполные имена и полные имена (неполные имена) преобразуются во время компиляции в соответствии с текущими правилами импорта. Например, если пространство имен ABC было импортировано как C , то вызовы CDe() будут преобразованы в ABCDe() .
В пространстве имен ко всем квалифицированным именам, которые не преобразуются в соответствии с правилами импорта, перед ними добавляется имя текущего пространства имен. Например, если CDe() вызывается в пространстве имен AB , CDe() будет преобразовано в ABCDe() .
Неполные имена классов преобразуются во время компиляции в соответствии с текущими правилами импорта (вместо коротких имен импорта используются полные имена). Например, если пространство имен ABC импортируется как C, new C() преобразуется в new ABC() .
Внутри пространства имен (например, AB) вызовы функций с неполными именами разрешаются во время выполнения. Например, вызов функции foo() анализируется следующим образом:
Найдите функцию с именем ABfoo() в текущем пространстве имен.
Попробуйте найти и вызвать функцию foo() в глобальном пространстве.
Вызовы неполных имен или классов полных имен (неполных имен) в пространстве имен (например, AB ) разрешаются во время выполнения. Ниже приведен процесс анализа вызова new C() и new DE() : Анализ new C() :
Найдите классы ABC в текущем пространстве имен.
Попробуйте автозагрузить классы ABC .
Анализ нового DE() :Добавьте к имени класса текущее имя пространства имен, чтобы оно стало: ABDE , а затем найдите класс.
Попробуйте автозагрузить класс ABDE .
Чтобы обратиться к глобальному классу в глобальном пространстве имен, необходимо использовать полное имя new C() .