Пространства имен в PHP
Работая со сложными сценариями, может возникнуть ситуация, когда при инициализации переменной или функции возникает непреднамеренное дублирование имен, что нарушит ход компиляции скрипта и выдаст ошибку. В этом уроке мы рассмотрим выжное понятие в PHP – пространства имен, применяя которое мы избавимся о ошибкок, связанных с дублированием имен в вашем сценарии.
Пространства имен в PHP
Пространства имен — это квалификаторы, которые решают две разные проблемы:
- Позволяют использовать одно и то же имя для более чем одного класса и предотвратить конфликт имен между вашим кодом и сторонним.
- Пространства имен могут сделать наш код более организованным, группируя классы, которые работают вместе для выполнения задачи.
Если мы попытаемся определить две разные функции, но с одинаковыми именами, то PHP выдаст ошибку во время запуска кода. Проблема этого ограничения в том, что если вы используете чью-либо стороннюю библиотеку, предоставляющую класс например, с именем User
, то вы не можете создать свой собственный класс с таким же именем.
Пространства имен позволяют нам обойти эту проблему, и мы можем создать столько классов User
, сколько нам понадобится. Кроме того пространства имен позволят нам организовать код в удобные пакеты, а также обозначить свои права владения этим кодом.
Пространства имен и файловая структура
Концепция определения и вызова пространств имен аналогична обычной файловой структуре в наших операционных системах.
Представьте, что пространства имен — это папки, а файлы — классы:
- В папке /base/math может быть несколько файлов: numbers.php, calcul.php и так далее. Но не может быть двух файлов с одинаковым именем.
- Для доступа к numbers.php из файла calcul.php, вы можете напрямую обратиться к numbers.php
- В папке /base/mechanic также может быть несколько файлов: physics.php, electro.php и т.д. И здесь же у вас может быть файл numbers.php, даже если файл с этим именем существует в папке /base/math.
- Внутри папки /mechanic для доступа к numbers.php вы будете ссылаться /base/mechanic/numbers.php
- Внутри папки /mechanic, если вам нужно было сослаться на файл numbers.php, который находится в папке /base/ math, вам нужно будет использовать /base/math/numbers.php
Точно так же работает пространства имен.
Объявление пространства имен
Пространство имён задается с помощью ключевого слова namespace
, за которым следует имя пространства имён:
Синтаксис
<?php
namespace MyApp;
?>
Примечание: Декларация namespace
declare
). В противном случае ваш код будет недействительным.
Если мы добавим объявление пространства имен в начало файла PHP, все классы, функции и константы будут элементами этого пространства имен.
Создадим файл с именем Math.php
и добавим следующий код:
Пример
<?php
namespace Math;
function add($a, $b) {
return $a + $b;
}
const PI = 3.14;
class Geometry {
static function getCircleArea($radius) {
return PI * $radius ** 2;
}
}
?>
- Сначала мы объявляем пространство имен — namespace Math;. (Теперь, все классы, интерфейсы, константы и функции будут элементами этого пространства имен)
- Затем мы объявили функцию add().
- Затем константа класса PI.
- Затем класс Geometry.
Использование пространств имен
Следующим шагом создадим еще один файл с именем usage.php
и получим доступ к элементам указанного выше пространства имен Math
(функциям, константам и классам).
Пример
Попробуй сам »<?php
// включает файл Math.php
// Как будто у вас здесь был написан весь код Math.php
include_once 'Math.php';
echo Math\add(4,7); // 11
echo "<br>";
echo Math\PI; // 3.14
echo "<br>";
echo Math\Geometry::getCircleArea(5); // 78.5
?>
Примечание: Символ \
используется для перехода на уровень ниже в пространствах имен.
Когда одновременно используются несколько классов из одного и того же пространства имен, проще использовать ключевое слово namespace
, чтобы не прописывать каждый раз квалификатор Math\
.
В следующем примере мы получим доступ к элементам указанного выше пространства имен Math
без квалификатора Math\
:
Пример
Попробуй сам »<?php
namespace Math;
include_once 'Math.php';
echo add(3,9); // 12
echo "<br>";
echo PI; // 3.14
echo "<br>";
echo Geometry::getCircleArea(10); // 314.15
?>
Подпространства имен
В операционной системе папки внутри могут содержать другие папки. Таким же образом пространства имен могут содержать пространства имен. Они называются подпространствами имен.Пример
<?php
namespace Math\Geometry;
// ... ваши классы Geometry
?>
В следующем примере мы создадим пространство имен с именем Math
, а также добавим в него подпространства имен и классы:
- Создадим основное пространство имен: Math
- Добавим одно подпространство имен: Math\Geometry (для обработки геометрии)
- Создадим два класса: Math\Constants (для сохранения часто используемых констант) и Math\Geometry\Circle (для вычисления диаметра, площади, длины окружности)
Вот окончательная структура нашего проекта:
/src /Math /Geometry Circle.php Constants.php
Math/Constants.php
Пример
<?php
namespace Math;
class Constants {
const PI = 3.14159;
}
?>
Math/Geometry/Circle.php
Пример
<?php
namespace Math\Geometry;
class Circle {
public $radius;
public function __construct($radius) {
$this -> radius = $radius;
}
public function getDiameter() {
return $this -> radius * 2;
}
public function getArea() {
// (pi)(r^2)
return \Math\Constants::PI * $this -> radius ** 2;
}
public function getCircumference() {
// 2(pi)(r)
return 2 * \Math\Constants::PI * $this -> radius;
}
}
?>
Примечание:
В файле Circle.php мы прописали \Math\Constants::PI ссылаясь на константу в файле Constants.php. Это потому, что сценарий PHP выполняется всегда относительно текущего пространства имен. Когда пространство имен начинается с обратной косой черты ( \ ), то путь к имени элемента будет исчисляться относительно глобального пространства имен.
- Если бы мы просто прописали Constants::PI в файле Circle.php, то ссылка была бы ткой \Math\Geometry\ Constants::PI.
- Если бы мы использовали Math\Constants::PI (без обратной косой черты
\
) в файле Circle.php, то получили бы ссылку \Math\Geometry\ Math\Constants::PI
Наконец, давайте используем наши классы в файле index.php
, который должен находиться в корневой папке вашего проекта:
Пример
Попробуй сам »<?php
include_once 'src/Math/Constants.php';
include_once 'src/Math/Geometry/Circle.php';
$circle = new Math\Geometry\Circle(5);
echo $circle -> getDiameter(); // 10
echo "<br>";
echo $circle -> getArea(); // 78.5
echo "<br>";
echo $circle -> getCircumference(); // 31.4
?>
В примере выше мы первым делом включили файлы классов Constants.php
и Circle.php
. Затем использовал класс Math\Geometry\Circle
и его методы.
Важно отметить, что index.php
автоматически будет находиться в глобальном пространстве имен, так как мы не указали для него не одного из пространств имен.
Импортирование пространств имен
Если в нашем проекте предусмотрена иерархия пространств имен, мы можем импортировать интересующее нас пространство имен в тот или иной файл, используя ключевое слово use
.
Если вы добавите следующий код в свой index.php
, класс Math\Geometry\Circle
будет импортирован в текущую область:
Пример
Попробуй сам »<?php
use Math\Geometry\Circle;
$circle = new Circle(5); // класс Circle теперь находится в этом пространстве имен
echo $circle -> getDiameter(); // 10
echo "<br>";
echo $circle -> getArea(); // 78.5
echo "<br>";
echo $circle -> getCircumference(); // 31.4
?>
Вы можете импортировать как пространства имен, так и классы:
Пример
<?php
use Math\Geometry; // импорт пространства имен
use Math\Geometry\Circle; // импорт класса
?>
Псевдоним пространства имен
Может быть полезно присвоить пространству имен или классу псевдоним:
- Если у вас уже есть класс с таким же именем, как у импортируемого класса
- Когда вам нужно более удобное (или простое) имя для импортируемого класса
use
:
Пример
<?php
use Math\Geometry\Circle as Circ;
$circle = new Circ(5);
?>
В примере выше мы присвоили псевдоним Circ
классу Circle
.
Аналогично можно присвоить псевдоним пространству имен.