Пространства имен в PHP

Пространства имен в PHP

От автора: Разрабатывая сложное веб-приложение, может возникнуть ситуация, когда при объявлении функции или переменной произойдет дублирование имен, что незамедлительно приведет к ошибке. Поэтому в данном уроке мы с Вами рассмотрим очень полезное нововведение в PHP 5.3 – пространства имен, используя которое, можно позабыть о ошибках, связанных с дублированием имен элементов Вашего скрипта.

скачать исходникискачать урок

Понятие пространства имен

Для начала рассмотрим следующие два файла. Файл file1.php

<?php

function foo() {
	echo "File1";
}
?>

Файл file2.php

<?php

function foo() {
	echo "File2";
}?>

При этом обратите внимание, что в каждом из них объявлена функция foo(). Сразу хотел бы отметить, что сейчас мы еще не говорим о пространствах имен и ни коем образом их не объявляем. А значит, по умолчанию используется глобальное пространство имен. Теперь обратите внимание, на еще один файл в котором мы подключим два предыдущих файла и вызовем на исполнение функцию foo(). Файл index.php

<?php 

include "file1.php";
include "file2.php";

foo();
?>

Запустив данный файл в браузере, мы, конечно же, увидим ошибку, так как в данный момент у нас объявляется две функции, с одинаковыми именами:

Так же хотел бы отметить, что обращаясь к функции foo(), в данном случае мы используем неквалификационное имя – то есть это только идентификатор конкретной функции (имя функции, без учета пространства имен). Что бы предотвратить появление ошибки – используем пространства имен. Для этого в каждом из подключаемых файлов укажем собственное пространство имен, используя ключевое слово namespace. Файл file1.php

<?php
namespace File1;

function foo() {
	echo "File1";
}
?>

Файл file2.php

<?php
namespace File2;

function foo() {
	echo "File2";
}
?>

Обратите внимание, что объявляя пространство имен, обязательно необходимо прописывать ключевое слово namespace перед любым кодом PHP или отображением данных на экран, в противном случае будет ошибка. Теперь, если мы обновим данные в браузере – мы получим ошибку вида:

Скорее всего Вы догадались, ошибка означает, что не найдена функция foo(). Данная функция определена, но в других пространствах имен. Файл index.php использует глобальное пространство имен, поэтому обращаясь к функции foo(), используя неквалификационное имя, мы ни как не можем получить доступ к функциям foo(), объявленным в других пространствах имен. Для того, что бы получить доступ к функции foo(), файла file1.php, мы должны в начале имени функции указать пространство имен:

File1\foo();

При этом в браузере мы увидим отработку вызываемой функции:

Таким образом, мы указали интерпретатору языка PHP, где искать интересующую нас функцию (в каком пространстве имен, осуществлять поиск). И в нашем случае отработала функция foo() из файла file1.php. Но, каждый раз при вызове функций, или переменных, обращаться к пространствам имен не совсем удобно, поэтому в файле index.php, мы можем объявить пространство имен, которое нас интересует и соответственно вызвать функцию foo(), используя неквалификационное имя:

<?php 

namespace File3;

include "file1.php";
include "file2.php";

foo();

При этом, если мы перейдем браузер, то увидим, что функция нормально отрабатывает. Теперь давайте посмотрим, что будет, если я в текущем пространстве имен, обращусь к функции foo(), следующим образом:

File1\foo();

В этом случае мы увидим ошибку следующего вида:

Ошибка возникает, потому как мы с Вами обращаемся к функции, используя имя и пространство имен — File1\foo(), таким образом, мы используем квалификационное имя. Квалификационное имя элемента содержит пространство имен, а также идентификатор элемента (его имя). В этом случае, да и в случае с неквалификационными именами, интерпретатор PHP всегда будет добавлять объявленное пространство имен к имени вызываемого элемента. Таким образом, если мы в начале файла объявили пространство имен File1, и вызываем на исполнение функцию File1\foo() – интерпретироваться данная строка будет как File1\File1\foo(). А теперь давайте посмотрим, что будет, если я обращусь к функции foo(), следующим образом:

\File1\foo();

В этом случае мы увидим, что функция отлично отрабатывает.

Здесь, хотел бы отметить, что \File1\foo() – это полное квалификационное имя функции foo(). Полное квалификационное имя всегда начинается с обратного слеша и содержит полное пространство имен и идентификатор интересующего элемента (имя функции, переменой и т.д). Если мы обращаемся к полному квалификационному имени, то интерпретатор не будет учитывать объявленное ранее пространство имен при интерпретации.

Объявляя пространства имен, мы можем создавать некие иерархии пространств имен, к примеру. Файл file1.php

<?php
namespace MyProject\File1;

function foo() {
	echo "File1";
}
?>

Файл file2.php

<?php
namespace MyProject\File1;

function foo() {
	echo "File2";
}
?>

При этом в файле index.php, мы можем вызвать функцию foo(), следующим образом:

<?php 

namespace MyProject\File1;

include "file1.php";
include "file2.php";

foo()

Импортирование пространств имен и псевдонимы

Если в нашем проекте предусмотрена иерархия пространств имен, мы можем импортировать интересующее нас пространство имен в тот или иной файл, к примеру, в файле index.php импортируем пространство имен, используя ключевое слово use:

<?php 

use MyProject\File1;

include "file1.php";
include "file2.php";
include "MyProject/File3/My2.php";

File\foo();
?>

При этом мы не объявляем пространство имен, а только импортируем его и для вызова функций или переменных, необходимо обращаться к их пространствам имен. Но теперь достаточно обратиться только к дочернему пространству имен и интерпретатор PHP, выполнит поиск интересующего элемента в импортируемых пространствах имен.

Импортируя пространство имен, можно указать псевдоним, используя который можно ссылаться на пространство имен, к примеру:

<?php 

use MyProject\File1 as name;

include "file1.php";
include "file2.php";

name\foo();

В этом случае мы можем обращаться к интересующим нас элементам, используя псевдоним. При интепретации данный псевдоним будет заменен на импортируемое пространство имен, то есть, вызывая name\foo(), мы вызываем MyProject\File1\foo(). Очень удобно использовать импортирование пространств имен в связке с псевдонимами, работая с классами, к примеру, есть файл следующего содержания:

<?php
namespace MyProject\File3;

class My2 {
	public function foo() {
		echo __CLASS__.__METHOD__;
	}
}

Данный файл принадлежит к пространству имен MyProject\File3 и соответственно расположен по адресу MyProject\File3\My2.php, то есть иерархия пространств имен, точно соответствует структуре папок, в которых содержится данный файл. В файле index.php, мы подключим данный файл и импортируем его пространство имен, используя при этом псевдоним:

<?php 

use MyProject\File3\My2 as myclass;

include "file1.php";
include "file2.php";
include "MyProject/File3/My2.php";

var_dump(new myclass());

Обратите внимание я импортирую пространство имен и псевдоним назначаю непосредственно для класса, описанного в указанном пространстве имен, таким образом при создании объекта данного класса, я могу использовать псевдоним: new myclass(). Что собственно мы и видим при обновлении страницы браузера:

Еще хотел бы обратить Ваше внимание, на следующий пример, файл index.php:

<?php 

use MyProject\File3\My2 as myclass;

function __autoload($class) {
	echo "Имя создаваемого класса - ". $class."<br />";
	$class = str_replace("\\","/",$class);
	include $class.'.php';
}


var_dump(new myclass());

В данном примере, мы с Вами рассмотрим создание механизма автоматической загрузки классов, используя пространства имен. Обратите внимание, вначале импортируем пространство имен и назначаем псевдоним для имени класса. Далее описываем функцию __autoload($class), функцию автоматической загрузки классов, которая выполнится при создании ранее неопределенного объекта класса. Данная функция принимает параметром переменную $class, в которую попадет имя класса, объект которого мы пытаемся создать. В нашем случае, используется псевдоним myclass, который при интерпретации будет заменен на MyProject\File3\My2, а это полностью соответствует файловой структуре примера, остается только заменить обратные слеши на прямые и добавить расширение для файла.

При обновлении браузера, на экране мы увидим следующее:

Как Вы видите все успешно отрабатывает.

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

На этом данный урок завершен. Всего Вам доброго и удачного кодирования!!!

Курс по программированию на языке PHP

Изучите PHP с нуля до результата!

Смотреть курс

Метки: ,

Комментарии Вконтакте:

Комментарии Facebook:

Комментарии (1)

  1. Алексей

    Я только начинаю изучать PHP и данный обучающий ролик пришлось несколько раз пересмотреть, и в итоге он дал превосходное понимание пространств имён в ООП. Теперь начинаю понимать CMS OpenCart , как всё реализованно. Автору ОГРОМНОЕ СПАСИБО! , большой толчок в изучении PHP дал

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree