Переменная определяет значение, но может быть ссылкой на другую переменную и иметь ее значение. В процессе исполнения алгоритма переменная обычно принимает множество различных значений. Константа хранит только одно значение. Объект непредсказуем: ему свойственно иметь структуру, содержание и множество особенностей.
Пространство имен - это совокупность переменных, констант, объектов, функций и иных конструкций, созданных разработчиком, на которые можно ссылаться через имя этого пространства имен.
Имена: сфера описания данных и алгоритмов
Имена элементов (переменных, констант, объектов, функций и других конструкций разработчика) никогда не пересекаются. Любое совпадение имен 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 >= 5.3.0, PHP 7)
Before discussing the use of namespaces, it is important to understand how PHP knows which namespaced element your code is requesting. A simple analogy can be made between PHP namespaces and a filesystem. There are three ways to access a file in a file system:
- Relative file name like foo.txt . This resolves to currentdirectory/foo.txt where currentdirectory is the directory currently occupied. So if the current directory is /home/foo , the name resolves to /home/foo/foo.txt .
- Relative path name like subdirectory/foo.txt . This resolves to currentdirectory/subdirectory/foo.txt .
- Absolute path name like /main/foo.txt . This resolves to /main/foo.txt .
- Unqualified name, or an unprefixed class name like $a = new foo(); or foo::staticmethod(); currentnamespace , this resolves to currentnamespace\foo foo . One caveat: unqualified names for functions and constants will resolve to global functions and constants if the namespaced function or constant is not defined. See Using namespaces: fallback to global function/constant for details.
- Qualified name, or a prefixed class name like $a = new subnamespace\foo(); or subnamespace\foo::staticmethod(); . If the current namespace is currentnamespace , this resolves to currentnamespace\subnamespace\foo . If the code is global, non-namespaced code, this resolves to subnamespace\foo .
- Fully qualified name, or a prefixed name with global prefix operator like $a = new \currentnamespace\foo(); or \currentnamespace\foo::staticmethod(); . This always resolves to the literal name specified in the code, currentnamespace\foo .
Here is an example of the three kinds of syntax in actual code:
namespace Foo \ Bar \ subnamespace ;
const
FOO
=
1
;
function
foo
() {}
class
foo
{
}
?>
namespace
Foo
\
Bar
;
include
"file1.php"
;
const
FOO
=
2
;
function
foo
() {}
class
foo
{
static function
staticmethod
() {}
}
/* Unqualified name */
foo
();
foo
::
staticmethod
();
echo
FOO
;
/* Qualified name */
subnamespace
\
foo
();
// resolves to function Foo\Bar\subnamespace\foo
subnamespace
\
foo
::
staticmethod
();
// resolves to class Foo\Bar\subnamespace\foo,
// method staticmethod
echo
subnamespace
\
FOO
;
// resolves to constant Foo\Bar\subnamespace\FOO
/* Fully qualified name */
\
Foo
\
Bar
\
foo
();
// resolves to function Foo\Bar\foo
\
Foo
\
Bar
\
foo
::
staticmethod
();
// resolves to class Foo\Bar\foo, method staticmethod
echo \
Foo
\
Bar
\
FOO
;
// resolves to constant Foo\Bar\FOO
?>
Note that to access any global class, function or constant, a fully qualified name can be used, such as \strlen() or \Exception or \INI_ALL . ?>
PHP, начиная с версии 5.3, подарил нам пространство имен. С тех пор идет где-то вялое, а где-то бурное обсуждение, как же это пространство имен использовать?
Некоторые фреймворки, такие как Symphony, Laravel, и, конечно же Zend взяли эту технологию на вооружение.
Все это более или менее вписалось в схему MVC. Осталась одна, наверное вечная, дискуссия, какой же должна быть главная брачная пара приложения - Модель и Контроллер?
Одни нам говорят, что Модель должна быть дородной и толстой и при ней стройный и тонкий Контроллер. Одним словом - матриархат.
Другие, наоборот, считают, что Контроллер должен всем управлять и повелевать, поэтому он получается основательный, упитанный. И при нем худенькая, стройненькая Модель, задача которой сводится к подай-принеси. Такой вот патриархат.
Так что же лучше в схеме MVC? Патриархат или матриархат?
Давайте посмотрим на это с точки зрения построения семейной ячейки на основе демократии. И пусть Namespace нам в этом поможет.
Нам не нравятся толстые, неуклюжие Контроллеры, которые, как слон в посудной лавке, по неосторожности могут раздавить все приложение.
Нам не нравятся также толстые Модели. Ну а кому они нравятся? Они должны быть достойны подиума!
Давайте попробуем с помощью Namespace, как с хорошей сватьей, создать гармоничную семью.
Сначала создадим каркас приложения. Как это ни банально, но пусть это будет блог.
Мы создали основну структуру, где:
- Blog - это хранилище нашего приложения;
- Views и Templates - хранилище представлений и шаблонов;
- Utility - хранилище общих библиотек;
- index.php - bootstrap скрипт;
- Post - вот здесь и должна состояться семейная идиллия Контроллера и Модели.
С index.php все просто:
run(); /* * end of index.php */
Определяем нужные пути и создаем автозагрузчик.
Автозагрузчик загружает необходимые классы, которые расположены в иерархии папок согласно пространству имен класса. Например, класс BlogPostServicesView будет разыскиваться в Blog/Post/Services.
А вот и первая встреча с Namespace.
При старте index.php мы создаем экземпляр приложения Blog, класс которого загружается из Blog/Blog.php.
Посмотрим на него.
post = new Post(); } public function run() { $this->post->view->all(); } }//end class Blog
При создании класса Blog мы внедряем в него класс Post с Namespace BlogPost и автозагрузчик загружает его из Blog/Post/Post.php.
Наверное, этот класс и можно назвать Контроллером,
view = new View(); } }//end class Post
Сущность Post включает в себя:
- структуру самой записи данных - BlogPostEntitiesPostEntity.php
Службы, обслуживающие запросы Контроллера - BlogPostServicesView.php (одна из служб, для примера)
db = new DB(); }//end __construct public function all() { $posts = $this->db->survey(); Contemplate::compose(array("header" => "header", "main" => "main", "footer" => "footer",), array("posts" => $posts, "title" => "Viper site",)); } }//end class PostView
Систему взаимодействия с базой данных - BlogPostRepositoriesDB.php - вот она, наша тонкая, изящная Модель,
Только подай-принеси, и ничего больше!
dbh = new PDO("mysql:host=localhost;dbname=test", $user, $pass, array(PDO::ATTR_PERSISTENT => true));
} catch (PDOException $e) {
echo "Error!: " . $e->getMessage() . "
";
die();
}
}//end __construct
public function survey()
{
$query_view = $this->dbh->prepare("SELECT * from posts");
$query_view->execute();
return $query_view->fetchAll(PDO::FETCH_CLASS, "BlogPostEntitiesPostEntity");
}//end survey
}//end class Db
В результате нам удалось создать структуру приложения, где все компоненты хорошо связаны, при этом мы добились четкого разделения классов, где каждый класс выполняет свою задачу. Контроллер у нас тонкий и в то же время мощный. Модель под стать ему. Идеальная семья!
И все багодаря Namespace.
Не спорю, во многих случаях удобен фреймворк. Но, посмотрите, Namespace вам ничего не напоминает?
Четкое разделение на классы, строгая, и в тоже время гибкая, полностью подчиненная разработчику иерархия каталогов и классов.
Отсутствие порою такого весомого довеска в виде сотен файлов и классов в виде фреймворка.
Отсутствие прокрустова ложа правил взаимодействия классов и компонентов.
Статья навеяна размышлениями на эту тему Taylor Otwell, автора фреймворка Laravel, за что ему огромное спасибо.
Адрес исходников примера на GitHub.
Здравствуйте. В сегодняшней статье мы рассмотрим, что такое пространства имён в 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;
}
?>
Итак, на этом сегодня всё. Больше информации и практические знания вы можете получить, пройдя курс