Здравствуйте. В сегодняшней статье мы рассмотрим, что такое пространства имён в PHP .
Если вы давно используете ООП , то, наверное, встречали ситуацию, когда, подключая стороннюю библиотеку, у вас случался сбой из-за того, что вы уже используете в своём коде такие же имена классов, как и в библиотеке. Особенно это может случиться, если вы используете такие распрастранённые имена, как "model" , "db" и т.п. О том, как это исправить, я сейчас и расскажу.
Пространство имён(namespace) - это некоторое хранилище, созданное для абстрактной группировки уникальных идентификаторов(имён).
Т.е. если вы будете использовать пространства имён , то сможете смело подключать сторонние библиотеки и не бояться, что там будут такие же имена, как и в вашем коде. Покончим с теорией и давайте перейдём к практике.
Создадим файл myclass.php с таким содержанием
namespace my\oneProject;
class MyClass { }
?>
Здесь мы создали класс в пространстве имён my\oneProject . Кстати, нужно писать именно обратный слеш. Не перепутайте!
Теперь в файле index.php напишем следующее
require_once("myclass.php");
$mc = new MyClass(); // Ошибка: класс не найден
$mc = new my\oneProject\MyClass(); // всё работает
?>
Как видите, теперь создать класс просто так не получится, нужно обязательно указывать, в каком пространстве имён он лежит.
Мы можем указывать сразу несколько пространств имён в одном файле
namespace Project;
Const CONNECT_OK = 1;
class Connection { }
function connect() { }
Namespace AnotherProject;
Const CONNECT_OK = 1;
class Connection { }
function connect() { }
?>
Не смотря на то, что у нас абсолютно идентичные названия классов, функций и констант, у нас не будет конфликта имён, т.к. они лежат в разных пространствах.
Мы можем также применять синтаксис со скобками.
namespace Project {
Const CONNECT_OK = 1;
class Connection { }
function connect() { }
}
Namespace AnotherProject {
Const CONNECT_OK = 1;
class Connection { }
function connect() { }
}
?>
Если вы объединяете код в глобальном пространстве имён с кодом в других пространствах, то используется только синтаксис со скобками.
namespace Project {
Const CONNECT_OK = 1;
class Connection { }
function connect() { }
}
Namespace { // глобальный код
session_start();
$a = Project\connect();
echo Project\Connection::start();
}
?>
Также, не забывайте, что определение пространства имён всегда должно идти первой строчкой кода. Если вы напишите так, то будет ошибка
Чтобы узнать, в каком пространстве имён вы сейчас находитесь, можно воспользоваться константой __NAMESPACE__
namespace Project;
echo """, __NAMESPACE__, """; // выведет "Project"
?>
С помощью данной константы можно, например, динамически конструировать имена
namespace Project;
Function incl($classname) {
$a = __NAMESPACE__ . "\\" . $classname;
return new $a;
}
?>
Итак, на этом сегодня всё. Больше информации и практические знания вы можете получить, пройдя курс
Недавно инкапсулировал свой проект в namespace и столкнулся с проблемой отсутствия нормальной документации. Все, что удалось найти датируется примерно 2009 годом, а на дворе почти 2012… В найденном материале куча нерабочих мест, использующих то, что в нынешней версии php нет. В связи с этим хочу немного осветить этот вопрос.
Итак, что же такое Namespace или пространство имен? Великая wikipedia определяет их так:
Пространство имён (англ. namespace) - некоторое множество, под которым подразумевается модель, абстрактное хранилище или окружение, созданное для логической группировки уникальных идентификаторов (то есть имён). Идентификатор, определенный в пространстве имён, ассоциируется с этим пространством. Один и тот же идентификатор может быть независимо определён в нескольких пространствах. Таким образом, значение, связанное с идентификатором, определённым в одном пространстве имён, может иметь (или не иметь) такое же (а скорее, другое) значение, как и такой же идентификатор, определённый в другом пространстве. Языки с поддержкой пространств имён определяют правила, указывающие, к какому пространству имён принадлежит идентификатор (то есть его определение).wiki
Все ясно? На самом деле все просто. До версии 5.3 в php существовало всего два пространства - глобальное(в котором выполнялся ваш основной код) и локальное(в котором определялись переменные функций).
С версии 5.3 все изменилось. Теперь можно определить свое пространство имен, в котором будут существовать ваши классы методы и т.д.
Надеюсь стало немного понятнее.
Я специально обозвал классы одинаково. Так они определены в разных пространствах, то это два разных класса, несмотря на одинаковые имена. Основной скрипт,-по прежнему, функционирует в глобальном пространстве, здесь ничего не изменилось и в нем, по-прежнему, можно определять классы и функции. Так для чего же тогда нужны пространства? Прежде всего, для уверенности в том, что когда вы подключаете файл, с каким-нибудь фреймворком или библиотекой, ваши классы не переопределят классы фреймворка или наоборот.
Для того, чтобы использовать классы определенные в своем пространстве имен, необходимо в нужном месте(я как правило предпочитаю делать это в начале файла) импортировать определенное вами пространство в глобальное для этого используется ключевое слово use
Внимание: по каким-то своим основаниям php не допускает использование ключевого слова use в блоках условий и циклах
Возьмем пример с картинок и воплотим его в коде:
Внимание: ключевое слово namespase должно быть расположено в самом начале файла сразу после php
файл A.php
php namespace A { class A { public static function say() { echo "Я пространство имен А"; } } }
файл B.php
php namespace B { class A { public static function say() { echo "Я пространство имен B"; } } }
Возможен альтернативный синтаксис:
php namespace A; class A { public static function say() { echo "Я пространство имен А"; } }
Рекомендуется объявлять каждое пространство имен в отдельном файле. Хотя можно и в одном, но это строго не рекомендуется!
Теперь переместимся в третий файл, в котором будет функционировать наш основной скрипт
index.php
php
require_once "A.php";
require_once "B.php";
use A\A;
use B\A;
казалось бы в чем преимущество, только кода прибавилось, однако это не совсем так, чуть дальше я приведу пример класса автозагрузки, с которым строки подключающие файлы с классами будут ненужны.
А теперь обратимся к нашим классам
php
require_once "A.php";
require_once "B.php";
use A\A;
use B\A;
A\A::say();
B\A::say();
Внимание: использование оператора разрешения области видимости (::) в пространствах имен php не допускается ! Единственное для чего он годится - это для обращения к статичным методам класса и константам. Вначале хотели использовать для пространства имен именно его, но затем из-за возникших проблем отказались. Поэтому конструкция вида A::A::say(); недопустима и приведет к ошибке.
Для пространств имен необходимо использовать символ обратного слеша "\"
Внимание: во избежание недоразумений необходимо экранировать данный символ при его использовании в строках: "\\"
Пространства имен можно вкладывать друг в друга, дополним наш файл A.php:
php
namespace A
{
class A
{
public static function say()
{
echo "Я пространство имен А";
}
}
}
namespace A\subA
{
class A
{
public static function say()
{
echo "Я подпространство имен А";
}
}
}
а в индексе напишем следующее:
php
require_once "A.php";
require_once "B.php";
use A\A as A;
use B\A as B;
use A\subA as sub
A::say();
A::say();
sub::say();
Важным моментом является использование алиасов для импортированных пространств. Можно было написать A\subA::say(); согласитесь, каждый раз писать полные пути к пространствам затруднительно для того, чтобы этого избежать были введены алиасы. При компилировании произойдет следующее вместо алиаса sub будет подставлено A\subA, таким образом мы получим вызов A\subA::say();
А что же тогда происходит при вызове функций определенных в глобальном пространстве? PHP сначала ищет функцию внутри того пространства, где вы сейчас работаете, и в случае если не находит, то обращается к глобальной области видимости. Для того, чтобы сразу указать, что вы используете глобальную функцию необходимо перед ней поставить обратный слеш.
Для того чтобы не было проблем с автозагрузкой классов из пространств файловую систему нужно организовать аналогично организации пространств. Например, есть у нас корневая папка classes, где и будут храниться наши классы, тогда наши пространства могут быть организованы следующим образом
classes\A\A.php
classes\A\sub\A.php(подпространство sub вынесем в отдельный файл)
classes\B\B.php
В php есть магическая константа __NAMESPACE__ которая содержит имя текущего пространства.
А теперь об автозагрузке.
Приведенный ниже класс не мой, я только сделал его рабочим и немного усовершенствовал взят отсюдова .Внимание: Для того, чтобы ваши классы загружались имя класса должно совпадать с именем файла!
" .$file ." in " .$filepath));
if (file_exists($filepath))
{
if(Autoloader::debug) Autoloader::StPutFile(("подключили " .$filepath));
$flag = FALSE;
require_once($filepath);
break;
}
Autoloader::recursive_autoload($file, $path2, &$flag);
}
}
closedir($handle);
}
}
private static function StPutFile($data)
{
$dir = $_SERVER["DOCUMENT_ROOT"] ."/Log/Log.html";
$file = fopen($dir, "a");
flock($file, LOCK_EX);
fwrite($file, ("║" .$data ."=>" .date("d.m.Y H:i:s") ."
║
" .PHP_EOL));
flock($file, LOCK_UN);
fclose ($file);
}
}
\spl_autoload_register("yourNameSpace\Autoloader::autoload");
}
Если посмотреть на имена классов, которые приходят для загрузки, то будет видно, что каждый класс предваряется префиксом из пространства имен, которое указано в use. Именно поэтому рекомендую использовать расположение файлов в каталогах аналогично пространству имен, это ускоряет поиск до одной-двух итераций.
Теперь наш индекс можно написать так:
php
require_once "Autoloader.php";
use Autoloader as Autoloader;
use A\A as A;
use B\A as B;
use A\subA as sub
A::say();
A::say();
sub::say();
теперь все классы и интерфейсы, которые вы будет использовать будут загружены автоматически.
Для демонстрации некоторых динамических возможностей языка с пространствами объявим еще один класс:
test.php
php
namespace mySpace
{
class test
{
__construct()
{
//конструктор;
}
function sayName($name)
{
echo "Привет " . $name;
}
static function sayOther()
{
echo "статичный вызов";
}
}
}
Index.php
php
require_once "Autoloader.php";
use Autoloader as Autoloader;
use mySpace\test as test
//можно, например сделать так
$class = "test";
//приведет к вызову конструктора
$obj = new $class;
$obj->sayName("test");
//а можно так
test\sayName("test2");
//или так
$obj::sayName("test");
//а можно так
test::sayName("test2");
Надеюсь, что моя статья будет полезна кому-нибудь.
Переменная определяет значение, но может быть ссылкой на другую переменную и иметь ее значение. В процессе исполнения алгоритма переменная обычно принимает множество различных значений. Константа хранит только одно значение. Объект непредсказуем: ему свойственно иметь структуру, содержание и множество особенностей.
Пространство имен - это совокупность переменных, констант, объектов, функций и иных конструкций, созданных разработчиком, на которые можно ссылаться через имя этого пространства имен.
Имена: сфера описания данных и алгоритмов
Имена элементов (переменных, констант, объектов, функций и других конструкций разработчика) никогда не пересекаются. Любое совпадение имен PHP интерпретирует как серьезную ошибку, а в случаях, когда он не может однозначно идентифицировать проблему, разработчик получает код, работающий не так, как было задумано, либо белое поле в браузере.
Все имена всех данных должны быть уникальны, поскольку пространство глобальное. Имена объектов и функций также не должны повторяться, но сфера глобальной видимости прерывается в телах методов объектов и функций. Здесь функционирует свое, локальное пространство имен и ничто не мешает именовать что-то внутри так же, как обозначено снаружи.
Приведенный пример - классика, если не обращать внимания на ключевое слово namespace: все, как всегда. Работает второй include. Префикс NameSpaceTwo\ перед именами функций уточняет, из какой вставки берется код.
Если из первой функции убрать ключевое слово global и операцию $iExt = 1; перенести на строчку выше, то про значение переменной 100 не будет знать ни первая функция, ни вторая.
Пространства имен: множество сфер описания
В показанном примере есть общий файл, который использует две вставки. В каждой вставке есть одна и та же функция scCheckName(). Какую из них выбрать, решает программист посредством имени того пространства, которое актуально в нужный момент времени в нужном месте кода.
Тот факт, что одно и то же имя присутствует в общем коде (после слияния вставок) не приводит к ошибке по той простой причине, что каждый файл вставки помечен своим собственным уникальным именем.
В первом файле все, что будет в нем описано, связывается с именем NameSpaceOne. Во втором файле все описания будут привязаны к имени NameSpaceTwo.
Допускается любое дублирование имен в обоих файлах, но в каждом из них любое имя элемента (переменной, константы, объекта, функции) должно быть уникальным.
В этом примере смена имени пространства имен в вызове функции scCheckName() избавила переменную $iExt второго пространства имен от изменения. Именно поэтому в примере специально выделено слово "изменена" - изменение на самом деле не состоялось. Значение переменной осталось прежним.
Тестирование и множественное проектирование
Эти простейшие примеры показывают: можно легко упростить разработку сложных проектов, повысить эффективность, производительность и ускорить работу. Однозначно, сразу появились первые идеи применения пространства имен:
- безопасное тестирование скриптов - путем замены "рабочих" пространств на тестовые аналоги;
- безопасное проектирование большими коллективами разработчиков - путем предоставления им "индивидуальных" пространств описания элементов.
На самом деле пространство имен имеет гораздо более важное значение. Язык PHP, пространство имен и каждый элемент описания (переменная, константа, объект...) уже очень давно предоставили разработчику возможность самостоятельно манипулировать синтаксисом и семантикой.
Конструкции языка и общее правило современного программирования: "понято" - исполнено - есть противоречие - "белый экран" на профессионального разработчика "не действует".
Многие программисты даже не в курсе, в каком месте искать сообщение PHP об ошибке, когда в браузере ничего нет (чистое белое поле). На определенном этапе своего развития программист мыслит синтаксисом и семантикой PHP, «работает» автоматом и результат: собственный синтаксис и собственная семантика в пределах дозволенного.
Белый экран - сразу однозначная реакция профессионального программиста и ошибка ликвидирована. Зачем тратить время на дебаггер и просмотр лога ошибок?
Объекты, массивы и пространства имен
Можно сказать, что переменные, константы и функции - это прошлый век, но они используются в разработке объектов. Хороший код - это когда алгоритм представлен взаимодействующими объектами, а не последовательностью корректных конструкций.
Если использовать массивы объектов, манипулировать идеей стека и последним (первым) элементом массива, то можно получить динамику: объекты сами "решают", как должен работать функционал сайта в зависимости от складывающейся ситуации.
На PHP пространство имен - это переменная особого рода, представленная собственным уникальным именем, часто сложно составленным. Имя пространства имен употребляется в коде. Если это строка, то можно одно пространство заменить на другое в ходе исполнения скрипта.
Если имена namespace PHP использует как значения переменных, то это еще более семантически нагруженный синтаксис, еще более сильный, чем массивы объектов.
Объект - это структура и содержание, которые характеризуются единством. Пространство имен - это множество объектов, элементов и связей между ними.
Нельзя проводить эксперименты на работающей системе, но благодаря namespace PHP предоставляет возможность моделировать реальную работающую систему в другом пространстве для целей:
- дальнейшего развития;
- тестирования;
- технического обслуживания и пр.
Если абстрагироваться от синтаксиса, предложенного разработчиками PHP, и представить пространства имен как глобальные сложные системы объектов, то горизонты возможностей расширяются многократно.
Синтаксис и применение пространства имен
Слово namespace PHP принимает только в первой строчке кода каждого файла. Все описания должны идти только за ним. Синтаксис включает в себя только имя, обозначенное в обычном понимании имени.
Существенно использовать правильные слова, отражающие смысл. Лучше, когда имя длинное, но в нем есть то, что дает четкое понимание, о каком пространстве идет речь, что оно делает, что описывает, что принимает или для чего создано.
Пространства могут быть вложены друг в друга до бесконечности, но этим не следует злоупотреблять. Имя должно быть понятным, вложенность - обоснована, а последовательность имен пространств должна иметь логику.
В применениях use и namespace, PHP допускает сложное кодирование, но всегда, когда есть такая возможность, лучше обойтись простым вариантом.
Общее правило: namespace - описание и это один файл, use - это импорт пространства в скрипт использования и назначение ему псевдонима (короткой ссылки).
Простой пример автозагрузки классов (объектов)
В задаче имеется объект для манипулирования строками, стилями оформления элементов страницы (описания CSS), объект даты, файловой системы и базы данных. Смысл реализации - создать по этим пяти позициям простые интерфейсы с целью использования нужных возможностей только через методы этих объектов.
Никакого прямого использования функций и конструкций языка не допускается. В такой задаче используется на PHP автозагрузка классов. Namespace рассматривается как совокупность объектов, находящихся в определенном месте файловой системы. Обычно, все объекты размещаются в файловой системе по смыслу, по папкам и в файлах с определенным названием.
В коде слева обозначено создание нужных пяти объектов, но где именно они находятся, не указано. В коде справа приведен текст автозагрузчика (основной скрипт), который при загрузке классов (объектов) автоматом подставляет нужный путь до места размещения объекта и расширение файла.php.
Пример множества пространств имен
Библиотека PhpOffice / PhpWord - качественный пример использования сложной иерархии множества пространств имен. Папка элементов содержит практически весь спектр элементов, доступных при формировании документа *.docx (MS Word), другие папки содержат необходимый инструментарий для работы с элементами, параграфами и таблицами.
Собственно, библиотека помещена в папку проекта по той причине, что пространство функциональности PhpOffice / PhpWord требовалось дополнить конкретным инструментарием и в конечном итоге создать собственный вариант аналогичного продукта.
Загрузка множества классов различных пространств имен
Использование PHP namespace autoload, когда необходимо загружать множества классов, а иерархия разработанной системы объектов достаточно сложна и представить ее сложно, приводит к необходимости создания жестких конструкций.
Ориентация разработчика (использующего продукт для продолжения работ) возможна только в контексте семантики (понимания проекта), которая представлена надлежащими сочетаниями слов, отражающих реальное значение и взаимосвязи объектов.
Необходимость применения библиотеки в индивидуальном проекте приводит к решению задачи, как сочетать пространства имен разработчика и авторов PhpOffice / PhpWord. Лучшим является размещение данного продукта (его пространств и объектов) в собственном пространстве проекта.
Существенно отметить, что без модификации пространств имен данного продукта на уровне его абстрактных элементов и загрузки классов обойтись не удастся. Это свидетельствует, что на PHP namespace использование внутренних пространств имен может быть выполнено недостаточно абстрактно и универсально.
Файловая система и локализация пространств
По существу, пространства имен - это «начертание» пути в файловой системе к нужному объекту. Использование имен файлов в качестве имен объектов - естественно и привычно. Использование имен папок в качестве именования пространств имен - объективно.
«Деревянная» организация информации достаточно громоздка в применении и усложняет разработку, но она является естественным представлением для систем объектов.
Проблема состоит в том, что этап разработки представлен определенным редактором кода, который сочетает в себе и видимое представление папок и содержание конкретной папки, но еще нет такого редактора, который бы обеспечивал сквозное движение по объектам и по папкам.
Проблема абстрактности и универсальности
Принято сознанием разработчика и объективно в действительности:
- дает абстракцию и возможность манипулировать информацией согласно ее реальной семантике;
- пространства имен отражают положение скриптов, объектов и отчасти смысла проекта в файловой системе
Фактически, соединив абстракцию ООП на имена объектов (файлы) и наложив ее на файловую систему (папки) с адекватным формированием имен namepace (пути + имена), можно управлять формированием пространств имен в процессе исполнения скрипта.
Программирование уже приобрело мощную динамику развития, но, если перевести процесс и нагрузку этапа разработки с текстового редактора (в котором создаются скрипты и размещаются по деревьям папок) на идею формирования такого кода, который сам себя позволяет совершенствовать и размещать в нужном месте файловой системы - программирование поднимется на новую высоту.
Сегодня мы с Вами в стиле как для полных дэбилов, в хорошем смысле сиго слова, постараемся разобраться в том, что такое пространства имён в PHP 5.
Что такое пространство имён в PHP 5
Значит, как для полных дэбилов, опять же только в хорошем смысле этого слова, скажем, что пространства имён в PHP 5 (да и в С и С++) - это как имена городов России или Украины, которые содержат в себе имена улиц. Например в одном и том же городе, как и в пространстве имён, Москва к примеру, не может существовать несколько названий улиц с именем "Путлеровская 666" - согласны? Ок.
Кроме определяемых пространств имён существует ещё и глобальное пространство имён PHP, в котором тусуются все базовые функции и классы, а также те, которые были определены в подключаемых файлах и которым не было назначено определённое пространство имён. По анологии с реальной жизнью можно сказать, что бомжи, гопники, проститутки и другие приблуды по сути являются теми же функциями и классами, которым не было назначено определённое место жительства (пространство имён ) и которые живут просто в глобальном пространстве России, - ака "мой адрес не дом и не улица, мой адрес советский союз".
Глобальное пространство имён в PHP 5
Ранее, до версии PHP 5.3, как собственно и сейчас, все, находящиеся в подключаемых файлах, константы, функции и классы автоматически размещались в глобальном пространстве PHP.
Таким образом, если файл Liba1.php с константами, функциями и классами:
require_once ("Liba1.php" ) ; const MYCONST = "MYCONST CONTENT" ; function myFunction() { return __FUNCTION__ ; } class MyClass { static function whoAmI() { return __METHOD__ ; } }
Мы подключим в наш исполняемый файл, то они будут расположены в глобальном пространстве имён и будут доступны для прямого их вызова:
\n " ; echo myFunction() . "\n " ; echo MyClass:: whoAmI () . "\n " ; // or $obj = new MyClass() ; echo $obj -> whoAmI () ;
Обратим внимание на то, что согласно последнего стандарта PSR-4 (http://www.php-fig.org/psr/psr-4/) классы следует именовать с большой буквы, как и содержащие их файлы, а методы (функции определённые в классе ) с маленькой буквы - если наш класс назван MyClass , то и имя файла его содержащего должно быть MyClass.php . Соблюдение этого стандарта требуется для успешной автозагрузки классов (ака Autoloader ).
Теперь, когда мы малость раздуплили, что то оно такое пространство имён в PHP 5, то самое время немного поднапрячь моск более умным изложением выше изложенного по приведённым ниже ссылям:
Оператор namespace в PHP 5
Оператор namespace определяет/объявляет текущее пространство имён для класса или текущего исполняемого файла.
Вспомним аналогию пространств имён с городами. Пространства имён можно также сравнить с телефонным справочником (кодами городов), - например мы можем сказать " namespace 38\045 ", что это 38\045 (код страны\код города) пространство телефонов города Киева.
К примеру у нас имеется библиотека/файл с именем MyClass.php
Сам класс MyClass , его методы (функции) и свойства (переменные, константы), будут доступны только из пространства имён App .
Чтобы напрямую использовать MyClass из пространства имён App в нашем исполняемом файле/скрипте, мы должны либо объявить в нём то же " namespace App; " либо использовать " use App\MyClass; ":
whoAmI () ;
В этом примере мы подгружаем наш MyClass.php из той же директории где расположен и исполняемый файл, т.е. без соблюдения стандарта PSR-4. По идее " namespace App; " должно объявляться в файле класса, а не в исполняемом файле, и App при этом (для успешной автозагрузки) должно быть директорией, а имя класса " class MyClass {...} " соответственно именем файла MyClass.php , который должен быть доступен по адресу App/MyClass.php .
Если мы ручками подгрузим MyClass.php и не объявим " namespace App; " или " use App\MyClass; ", то получим " Fatal error: Class "MyClass" not found " ибо в файле класса MyClass.php объявлено пространство имён " namespace App; " (App) и только из него будет доступен класс MyClass , - разумеется если класс с таким же именем (MyClass) не объявлен в глобальном пространстве.
Для использования классов из пространств имён мы должны PHP попросить об этом директивами " use App\MyClass; " или " namespace App; ".
Для успешной автозагрузки мы должны соблюдать стандарт PSR-4 и располагать файлы классов в директориях имена которых соответствуют объявленному пространству имён. Например:
Пространство имён класса MyClass: " namespace App; " Физическое расположение файла: App/MyClass.php Пространство имён класса MyClass: " namespace App\Liba1; " Физическое расположение файла: App/Liba1/MyClass.php Пространство имён класса MyClass: " namespace App\Vasya\Liba1; " Физическое расположение файла: App/Vasya/Liba1/MyClass.php
Про "автозагрузку" классов в PHP 5 поговорим чуть папизже...
Оператор use в PHP 5
При помощи оператора use , мы сможем получить из другого пространства имён доступ к другому пространству имён или к классу.
Ни константы, ни функции не могут быть заимпортированы с помощью оператора use . Действию оператора use подвержены только имена классов и пространства имен. Хотя, кажись, начиная с версии PHP 5.6+ возможно импортирование функций и констант.
- Импорт и создание псевдонима для класса: use App\Liba1\MyClass as MyAlias;
- Импорт класса: use App\Liba1\MyClass;
- Импорт самого пространства имён: use App\Liba1;
- Импорт глобального класса: use ArrayObject;
Кто-то может спросить " А накой чёрт нам нужен "Импорт глобального класса"? ", - а нужен он для доступа к нему из какого-то пространства имён, например:
Потому как мы находимся в пространстве имён "Vasya", а РНР всегда работает из под текущего пространства имён, то выполнение приведённого выше кода завершится ошибкой " Fatal error: Class "Vasya\ArrayObject" not found in ". Чтобы получить доступ к классу ArrayObject находясь в пространстве имён Vasya нам нужно использовать (раскомментировать) " use ArrayObject; " или претворить имя класса обратным слешем \ArrayObject .
- Kласс ArrayObject позволяет работать с объектами как с массивами.
- PHP: Использование пространств имен: импорт/создание псевдонима имени - Manual
- PHP: Использование пространств имен: переход к глобальной функции/константе - Manual
- Часто задаваемые вопросы (FAQ): вещи, которые вам необходимо знать о пространствах имен
Автозагрузка классов в PHP 5
Нужно помнить, что PHP всегда работает в текущем пространстве имён. Это значит, что если мы объявили пространство имён " namespace Vasya; " и попытались создать объект класса " $obj = new MyClass(); ", то при использовании функции автозагрузчика "__autoload() " или "spl_autoload_register() " будет выполнена попытка подключить файл по адресу Vasya/MyClass.php . Например:
// Используем пространство имён Васи ) ; return true ; } return false ; } ) ; $obj = new MyClass() ; echo $obj -> whoAmI () ;
Для автоматической загрузки классов функция spl_autoload_register() считается более предпочтительной нежели __autoload() . Функция __autoload() не рекомендуется к использованию и в будущем её поддержка может быть прекращена или она и вовсе может быть удалена. С версии PHP 5.3.0 стало возможным использование безымянных функций (ака "function (){}" ).
Итоги
Появление в PHP пространств имён однозначно является положительным шагом. Если я где-то протупил, тогда, пожалуйста, поправьте меня своими комментариями.
P.S. Статья написана по просьбам трудящихся, которые не смогли осилить официальную документацию.
Недавно инкапсулировал свой проект в namespace и столкнулся с проблемой отсутствия нормальной документации. Все, что удалось найти датируется примерно 2009 годом, а на дворе почти 2012… В найденном материале куча нерабочих мест, использующих то, что в нынешней версии php нет. В связи с этим хочу немного осветить этот вопрос.
Итак, что же такое Namespace или пространство имен? Великая wikipedia определяет их так:
Пространство имён (англ. namespace) - некоторое множество, под которым подразумевается модель, абстрактное хранилище или окружение, созданное для логической группировки уникальных идентификаторов (то есть имён). Идентификатор, определенный в пространстве имён, ассоциируется с этим пространством. Один и тот же идентификатор может быть независимо определён в нескольких пространствах. Таким образом, значение, связанное с идентификатором, определённым в одном пространстве имён, может иметь (или не иметь) такое же (а скорее, другое) значение, как и такой же идентификатор, определённый в другом пространстве. Языки с поддержкой пространств имён определяют правила, указывающие, к какому пространству имён принадлежит идентификатор (то есть его определение).wiki
Все ясно? На самом деле все просто. До версии 5.3 в php существовало всего два пространства - глобальное(в котором выполнялся ваш основной код) и локальное(в котором определялись переменные функций).
С версии 5.3 все изменилось. Теперь можно определить свое пространство имен, в котором будут существовать ваши классы методы и т.д.
Надеюсь стало немного понятнее.
Я специально обозвал классы одинаково. Так они определены в разных пространствах, то это два разных класса, несмотря на одинаковые имена. Основной скрипт,-по прежнему, функционирует в глобальном пространстве, здесь ничего не изменилось и в нем, по-прежнему, можно определять классы и функции. Так для чего же тогда нужны пространства? Прежде всего, для уверенности в том, что когда вы подключаете файл, с каким-нибудь фреймворком или библиотекой, ваши классы не переопределят классы фреймворка или наоборот.
Для того, чтобы использовать классы определенные в своем пространстве имен, необходимо в нужном месте(я как правило предпочитаю делать это в начале файла) импортировать определенное вами пространство в глобальное для этого используется ключевое слово use
Внимание: по каким-то своим основаниям php не допускает использование ключевого слова use в блоках условий и циклах
Возьмем пример с картинок и воплотим его в коде:
Внимание: ключевое слово namespase должно быть расположено в самом начале файла сразу после php
файл A.php
php namespace A { class A { public static function say() { echo "Я пространство имен А"; } } }
файл B.php
php namespace B { class A { public static function say() { echo "Я пространство имен B"; } } }
Возможен альтернативный синтаксис:
php namespace A; class A { public static function say() { echo "Я пространство имен А"; } }
Рекомендуется объявлять каждое пространство имен в отдельном файле. Хотя можно и в одном, но это строго не рекомендуется!
Теперь переместимся в третий файл, в котором будет функционировать наш основной скрипт
index.php
php
require_once "A.php";
require_once "B.php";
use A\A;
use B\A;
казалось бы в чем преимущество, только кода прибавилось, однако это не совсем так, чуть дальше я приведу пример класса автозагрузки, с которым строки подключающие файлы с классами будут ненужны.
А теперь обратимся к нашим классам
php
require_once "A.php";
require_once "B.php";
use A\A;
use B\A;
A\A::say();
B\A::say();
Внимание: использование оператора разрешения области видимости (::) в пространствах имен php не допускается ! Единственное для чего он годится - это для обращения к статичным методам класса и константам. Вначале хотели использовать для пространства имен именно его, но затем из-за возникших проблем отказались. Поэтому конструкция вида A::A::say(); недопустима и приведет к ошибке.
Для пространств имен необходимо использовать символ обратного слеша "\"
Внимание: во избежание недоразумений необходимо экранировать данный символ при его использовании в строках: "\\"
Пространства имен можно вкладывать друг в друга, дополним наш файл A.php:
php
namespace A
{
class A
{
public static function say()
{
echo "Я пространство имен А";
}
}
}
namespace A\subA
{
class A
{
public static function say()
{
echo "Я подпространство имен А";
}
}
}
а в индексе напишем следующее:
php
require_once "A.php";
require_once "B.php";
use A\A as A;
use B\A as B;
use A\subA as sub
A::say();
A::say();
sub::say();
Важным моментом является использование алиасов для импортированных пространств. Можно было написать A\subA::say(); согласитесь, каждый раз писать полные пути к пространствам затруднительно для того, чтобы этого избежать были введены алиасы. При компилировании произойдет следующее вместо алиаса sub будет подставлено A\subA, таким образом мы получим вызов A\subA::say();
А что же тогда происходит при вызове функций определенных в глобальном пространстве? PHP сначала ищет функцию внутри того пространства, где вы сейчас работаете, и в случае если не находит, то обращается к глобальной области видимости. Для того, чтобы сразу указать, что вы используете глобальную функцию необходимо перед ней поставить обратный слеш.
Для того чтобы не было проблем с автозагрузкой классов из пространств файловую систему нужно организовать аналогично организации пространств. Например, есть у нас корневая папка classes, где и будут храниться наши классы, тогда наши пространства могут быть организованы следующим образом
classes\A\A.php
classes\A\sub\A.php(подпространство sub вынесем в отдельный файл)
classes\B\B.php
В php есть магическая константа __NAMESPACE__ которая содержит имя текущего пространства.
А теперь об автозагрузке.
Приведенный ниже класс не мой, я только сделал его рабочим и немного усовершенствовал взят отсюдова .Внимание: Для того, чтобы ваши классы загружались имя класса должно совпадать с именем файла!
" .$file ." in " .$filepath));
if (file_exists($filepath))
{
if(Autoloader::debug) Autoloader::StPutFile(("подключили " .$filepath));
$flag = FALSE;
require_once($filepath);
break;
}
Autoloader::recursive_autoload($file, $path2, &$flag);
}
}
closedir($handle);
}
}
private static function StPutFile($data)
{
$dir = $_SERVER["DOCUMENT_ROOT"] ."/Log/Log.html";
$file = fopen($dir, "a");
flock($file, LOCK_EX);
fwrite($file, ("║" .$data ."=>" .date("d.m.Y H:i:s") ."
║
" .PHP_EOL));
flock($file, LOCK_UN);
fclose ($file);
}
}
\spl_autoload_register("yourNameSpace\Autoloader::autoload");
}
Если посмотреть на имена классов, которые приходят для загрузки, то будет видно, что каждый класс предваряется префиксом из пространства имен, которое указано в use. Именно поэтому рекомендую использовать расположение файлов в каталогах аналогично пространству имен, это ускоряет поиск до одной-двух итераций.
Теперь наш индекс можно написать так:
php
require_once "Autoloader.php";
use Autoloader as Autoloader;
use A\A as A;
use B\A as B;
use A\subA as sub
A::say();
A::say();
sub::say();
теперь все классы и интерфейсы, которые вы будет использовать будут загружены автоматически.
Для демонстрации некоторых динамических возможностей языка с пространствами объявим еще один класс:
test.php
php
namespace mySpace
{
class test
{
__construct()
{
//конструктор;
}
function sayName($name)
{
echo "Привет " . $name;
}
static function sayOther()
{
echo "статичный вызов";
}
}
}
Index.php
php
require_once "Autoloader.php";
use Autoloader as Autoloader;
use mySpace\test as test
//можно, например сделать так
$class = "test";
//приведет к вызову конструктора
$obj = new $class;
$obj->sayName("test");
//а можно так
test\sayName("test2");
//или так
$obj::sayName("test");
//а можно так
test::sayName("test2");
Надеюсь, что моя статья будет полезна кому-нибудь.