php Автозагрузка классов и Пространства имен (namespaces) -- что их связывает и чем они "отличаются"

Сначала сделаем несколько замечаний отдельно по автозагрузке и отдельно по пространствам имен, потом опишем связи между ними и подведём итоги.

Автозагрузка классов в PHP

Несколько фактов об автозагрузке:

  • Автозагрузка (сегодня в PHP) -- это просто способ зарегистрировать одну или несколько функций (написанных, например, вами), которая/которые будут вызваны интерпретатором, в случае, если он не смог найти определение класса среди уже загруженных классов (это классы входного скрипта, а также все классы из файлов, которые уже были на момент обращения добавленны с помощью require/include).
  • Зарегистрированные функции (их называют "функции автозагрузки") в конечном итоге пытаются сделать всё то же -- по переданному имени класса, понять какой именно файл надо "заинклудить", происходит это так:
    1. Регистрируются функции автозагрузки с помощью стандартной функции spl_autoload_register('имяВашейФункции')
    2. Далее если класс ещё не загружен, то интерпретатор даёт возможность (по очереди) всем функциям автозагрузки, зарегистрированным на момент обращения к данному имени класса, найти и загрузить файл, содержащий определение данного класса.
    3. Если последнее не удаётся первой из зарегистрированных функций, интерпретатор вызывает следующую и т.д., пока либо нужный файл не будет загружен, либо не будет брошена ошибка о том, что определение класса найти не удалось.
  • Автозагрузка появилась в PHP до появления пространств имен (т.е. были версии PHP с автозагрузкой, но без поддержки пространств имён), поэтому вообще говоря, ваша функция автозагрузки может не работать с пространствами имен (даже если они есть), а скажем просто грузить все подряд из какой-нибудь конкретной папки.

Пространства имён в PHP

  1. Пространства имен служат прежде всего для того, чтобы избегать конфликтов имен из разных частей программы. (Ознакомьтесь с подробностями о пространствах имен.)
  2. Пространство имен, определяется в файле перед любым другим кодом с помощью ключевого слова namespace, например:
    <?php
    namespace MyProject;
    
    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }

    -- как видим в пространстве могут находится не только классы, также с помощью обратных слешей можно задать подпространство, с любым уровнем вложенности:

    <?php
    namespace MyProject\Sub\Level;
    
    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }
    
    ?>

В связи со сказанным выше поговорим о имени класса относительно разных пространств имен, для этого рассмотрим пример:

<?php
namespace application\controllers;
class HomepageController extends \ItForFree\SimpleMVC\mvc\Controller
{
    /**
     * @var string Название страницы
     */
    public $homepageTitle = "Домашняя страница";
    public $layoutPath = 'main.php';
      
    /**
     * Выводит на экран страницу "Домашняя страница"
     */
    public function indexAction()
    { }
}

-- этот класс имеет полное имя "\application\controllers\HomepageController",
полное имя состоит из:

  • собственного имени класса , в данном случае это: HomepageController
  • и пространства имен, в котором в котором находится класс application\controllers

(заметим и то, когда в начале слеш ставится, а когда нет)

Также в примере выше стоит обратить внимание на строку \ItForFree\SimpleMVC\mvc\Controller -- это полное имя класса-родителя для данного, он описан в некотором пространстве ItForFree\SimpleMVC\mvc (при это по пространству в общем случае нельзя сказать где именно располагается файл с классом).

Пространства имен и автозагрузка классов в PHP

Собственно, идея стандарта PSR-4 (и не только его) состоит в том, что описать правила связи между пространством имен и положением файлов с описанием этих классов в иерархии директорий приложения, если эта связь выполнена, то и появляется возможность глядя на полное имя класса (а функции автозагрузки интерпретатор передаёт его -- это имя) как раз понять -- как и где "искать" этот файл и подключать.
Это вытекает, в частности, и из того, что запись пространств имен напоминает пути в файловых системах.