# Введение в пространства имен в ООП на PHP

Если при запуске PHP скрипта будут два класса с одинаковыми именами, то они вступят в конфликт, что приведет к фатальной ошибке. Это на самом деле не очень удобно, так как постоянно приходится следить за уникальностью имен.

Для примера рассмотрим следующую ситуацию: у вас есть сайт, на котором есть пользователи и админ. При этом в папке `users` хранятся классы для юзеров, а в папке `admin` - классы для админа.

Пусть и для юзеров, и для админа нужен некий класс `Page`, отвечающий за какие-то страницы сайта. При этом для юзеров будет свой класс, а для админа - свой. В таком случае нас и поджидает конфликт имен.

Самый простой способ решения этого конфликта - дать отличающиеся имена классам, например, `UsersPage` и `AdminPage`. Этот путь, однако, постепенно ведет к появлению очень длинных имен классов.

В PHP существует и другой путь решения проблемы - пространства имен. Суть в следующем: каждый класс может относится к какому-то пространству имен и при этом уникальность имен классов должна соблюдаться только внутри этого пространства.

То есть, для решения нашей проблемы мы можем сделать следующее: отнести один класс `Page` к какому-нибудь пространству имен, например, `Users`, а второй класс `Page` отнести к другому пространству имен, например, `Admin`.

## Синтаксис пространств имен

Чтобы задать классу пространство имен, нужно первой строчкой файла, в котом хранится этот класс написать команду `namespace`, а после нее через пробел - название этого пространства.

Если класс относится к какому-нибудь пространству имен, то для создания объекта класса нужно будет указать не только имя класса, но и его пространство имен, разделенные обратным слешем. Давайте посмотрим на примере.

Пусть у нас есть класс `Page`, не относящийся ни к какому пространству имен. Тогда объект этого класса мы создадим следующим образом:

`<?php $page = new Page; ?>`

Пусть теперь этот класс принадлежит пространству имен `Admin`. В этом случае объект этого класса мы будем создавать уже вот таким образом:

`<?php $page = new \Admin\Page; ?>`

## Посмотрим на примере

Давайте разнесем классы для юзеров и классы для админа по разным пространствам имен, чтобы избежать описанных выше конфликтов классов.

Для класса `Page` из файла `/admin/page.php` укажем пространство имен `Admin`:

`<?php namespace Admin; class Page { } ?>`

А для класса Page из файла `/users/page.php` укажем пространство имен `Users`:

`<?php namespace Users; class Page { } ?>`

Давайте теперь в файле `/index.php` создадим объект одного и второго класса `Page`:

`<?php require_once '/admin/page.php'; require_once '/users/page.php'; $adminPage = new \Admin\Page; $usersPage = new \Users\Page; ?>`

Пусть у вас есть папка `core` и папка `project`. В каждой из папок есть свой класс `Controller`. Сделайте так, чтобы эти классы принадлежали разным пространствам имен. В файле `index.php` создайте объекты одного и второго классов.

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

Пусть теперь у нас есть более сложная ситуация: для админа нужно сделать два класса `Page` - один с данными страницы, а второй - с представлением этих данных. Пусть первый класс находится в файле `/admin/data/page.php`, а второй - в файле `/admin/view/page.php`.

Выше мы уже решили, что все классы из папки `admin` будут относится к пространству имен `Admin`. Однако, теперь в этом самом пространстве у нас конфликт двух классов. Для решения проблемы можно сделать дополнительные подпространства имен. Например, можно сделать пространство имен `Admin`, а в нем подпространства `Data` и `View`. В таком случае имена этих подпространств просто записываются через обратный слеш - как при задании пространства имен, так и при создании объекта класса.

Здесь следует уточнить, что уровень вложенности подпространств не ограничен (можно создавать под под пространства в подпространствах и так далее).

Итак, давайте доделаем наш описанный выше пример. Для класса `Page` из файла `/admin/data/page.php` укажем пространство имен `Admin\Data`:

`<?php namespace Admin\Data; class Page { } ?>`

Для класса `Page` из файла `/admin/view/page.php` укажем пространство имен `Admin\View`:

`<?php namespace Admin\View; class Page { } ?>`

Создадим объекты наших классов:

`<?php require_once '/admin/data/page.php'; require_once '/admin/view/page.php'; $adminDataPage = new \Admin\Data\Page; $adminViewPage = new \Admin\View\Page; ?>`

Пусть у вас есть папка `modules/cart`. Сделайте так, чтобы все классы из этой папки относились к пространству имен `Modules\Cart`.

Пусть у вас есть папка `modules/shop/cart/`. Сделайте так, чтобы все классы из этой папки относились к пространству имен `Modules\Shop\Cart`.

## Некоторые замечания

В примерах выше имена пространств имен совпадают с именами папок, в которых хранятся файлы. Делать так - хорошая практика, но обязательным это не является.

Пусть у вас есть папка `modules`, а в ней файл `marketCart.php` и файл `shopCart.php`. Пусть в обоих файлах размещается класс `Cart`. Сделайте так, чтобы класс из первого файла принадлежал пространству имен `Market\Cart`, а из второго файла - пространству `Shop\Cart`.

←→
↑