Если мы попытаемся определить две разные функции, но с одинаковыми именами, то PHP выдаст ошибку во время запуска кода:
<?php
// file: index.php
function foo()
{
print_r('one');
}
function foo()
{
print_r('two');
}
php index.php
# Невозможно переопределить существующую функцию
# Ошибка падает на втором определении
PHP Fatal error: Cannot redeclare foo() (previously declared in /private/var/tmp/index.php:3)
А если разнести определения этих функций по разным файлам и включить один в другой? Чуда не произойдет - как только интерпретатор встретит новое определение с таким же именем, как и старое, он завершит работу с ошибкой Cannot redeclare (невозможно переопределить существующую функцию).
Давайте порассуждаем над тем, почему это - проблема. Реальные приложения на PHP состоят из многих тысяч строк кода. Значительная часть этого кода приходит из библиотек, написанных другими людьми, и почти наверняка мы не знаем, как они там внутри устроены. Чем больше библиотек вы используете, чем больше разработчиков в проекте и, собственно, кода проекта, тем выше вероятность того, что возникнут дублирующиеся названия. Более того, может оказаться так, что две разные библиотеки, которые вам так нужны в проекте, имеют одинаковые имена функций, а, следовательно, вы физически не сможете их использовать вместе. А включение каждой новой библиотеки в код проекта почти наверняка заставит переименовывать функции самого проекта из-за конфликта имен. Когда-то эта проблема была настолько серьезной, что функции в PHP именовались с префиксами, например, mylibnameSendEmail()
или mylibnameAddNewUser()
. Таким образом пытались избежать коллизий (пересечений по именам).
Начиная с PHP версии 5.3 в языке появился механизм пространств имен, в задачу которого входит изоляция кода разных файлов друг от друга. Несмотря на то, что это - новый для нас механизм, сама концепция встречается в нашей жизни повсеместно. В файловой системе роль пространств имён выполняют директории, в телефонах - код страны, в адресах - страны, города и улицы. Последний пример демонстрирует вложенные пространства имён. Недостаточно знать только номер дома, чтобы понять, в какой квартире живет человек. Кроме этого, надо знать улицу, город и страну.
В подавляющем большинстве языков есть встроенные механизмы, аналогичные пространствам имён, причем в этих языках они существовали с самого начала, а не были добавлены потом. Часто они имеют другие имена, например, модули или пакеты. В каждом языке подобный механизм работает чуть-чуть по-своему, но все они предназначены для решения одной задачи – разрешения коллизий при именовании.
К сожалению, в силу исторических причин, пространства имён в PHP появились не с самого начала существования языка, как это принято при разработке языков. Из-за этого получилось, по сути, два независимых механизма, один - включение файлов как таковых, другой - пространства имён.
Пора переходить к примерам:
<?php
// math.php
namespace math;
function sum($a, $b)
{
return $a + $b;
}
Пространство имён задается с помощью ключевого слова namespace
, за которым следует имя пространства имён. Теперь посмотрим на то, как использовать функции, определенные в пространстве имён:
<?php
// index.php
require_once 'math.php';
// Обратиться напрямую к функции sum не получится:
// PHP Fatal error: Uncaught Error: Call to undefined function sum()
sum(3, 2);
// А если указать пространство имён, то все работает:
\math\sum(5, 8); // 13
Попытка обратиться к функции по имени приведет к ошибке, так как она скрыта за пространством имён. Правильный вызов выглядит так: \<имя пространства имён>\<имя функции>
. Рассмотрим еще один пример, когда функция с одним и тем же именем определена в разных пространствах имён.
<?php
// index.php
require_once 'text.php';
require_once 'number.php';
// Эта функция повторяет строчку, переданную первым параметром столько раз, сколько указано во втором параметре:
\text\multiply('hi', 3); // hihihi
\number\multiply(3, 2); // 6
Два пространства имён имеют одинаковые функции, но, как видно из кода, это не создает неудобств. Каждая функция вызывается с указанием собственного пространства имен. Более того, мы можем определить функцию multiply()
прямо в том месте, куда производится включение других пространств имён:
<?php
// main.php
require_once 'text.php';
require_once 'number.php';
namespace main;
function multiply($a, $b)
{
print_r('it works!');
}
function all()
{
\text\multiply('ho', 2); // hoho
\number\multiply(3, 2); // 6
// Такой вызов неявно подставляет текущее пространство \main\
multiply(2, 3); // it works!
}
Обратите внимание на последний вызов. Функции находящиеся внутри одного пространства имен могут вызывать друг друга напрямую.
Вам ответят команда поддержки Хекслета или другие студенты.
Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.
Загляните в раздел «Обсуждение»:
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.
Наши выпускники работают в компаниях:
С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.
Зарегистрируйтесь или войдите в свой аккаунт