Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос нашим менторам. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Пространство имен

Если мы попытаемся определить две разные функции, но с одинаковыми именами, то 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 в языке появился механизм пространств имен, в задачу которого входит изоляция кода разных файлов друг от друга. Несмотря на то, что это - новый для нас механизм, сама концепция встречается в нашей жизни повсеместно. В файловой системе роль пространств имён выполняют директории, в телефонах - код страны, в адресах - страны, города и улицы. Последний пример демонстрирует вложенные пространства имён. Недостаточно знать только номер дома, чтобы понять, в какой квартире живет человек. Кроме этого, надо знать улицу, город и страну.

Files Tree

В подавляющем большинстве языков есть встроенные механизмы, аналогичные пространствам имён, причем в этих языках они существовали с самого начала, а не были добавлены потом. Часто они имеют другие имена, например, модули или пакеты. В каждом языке подобный механизм работает чуть-чуть по-своему, но все они предназначены для решения одной задачи – разрешения коллизий при именовании.

К сожалению, в силу исторических причин, пространства имён в 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

Два пространства имён имеют одинаковые функции, но, как видно из кода, это не создает неудобств. Каждая функция вызывается с указанием собственного пространства имен. Более того, мы можем определить функцию multi() прямо в том месте, куда производится включение других пространств имён:

<?php

// main.php

require_once 'text.php';
require_once 'number.php';

namespace main;

function multi($a, $b)
{
    print_r('it works!');
}

function all()
{
    \text\multi('ho', 2); // hoho
    \number\multi(3, 2); // 6

    // Такой вызов неявно подставляет текущее пространство \main\
    multi(2, 3); // it works!
}

Обратите внимание на последний вызов. Функции находящиеся внутри одного пространства имен могут вызывать друг друга напрямую.


Дополнительные материалы

  1. Официальная документация

<span class="translation_missing" title="translation missing: ru.web.courses.lessons.mentors.mentor_avatars">Mentor Avatars</span>

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят менторы из команды Хекслета или другие студенты.

Зарегистрироваться

или войти в аккаунт

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг».

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг».