Перейти к основному содержимому

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

Разработчику Архитектору

Пространства имён PHP - уникальные имена классов

В крупном проекте десятки библиотек и сотни классов. Без разделения имён неизбежны коллизии: два пакета могут объявить класс User, Logger или Exception. Пространство имён (namespace) — это логический префикс, превращающий короткое имя в уникальное: App\Model\User и Vendor\Security\User — разные типы.

Пространства имён не создают «папки в памяти» и не влияют на производительность напрямую. Это соглашение об именовании, которое связывают с файловой структурой через PSR-4 и Composer. Подробнее об инструменте зависимостей: Composer.


Объявление и полное имя

Пространство объявляется в начале файла (до любого исполняемого кода, кроме declare):

<?php
declare(strict_types=1);

namespace App\Service;

class Mailer
{
public function send(string $to, string $body): void
{
// ...
}
}

Полное имя класса (FQCN)App\Service\Mailer. Внутри того же namespace можно писать коротко: new Mailer().

Вложенность отражает архитектуру, а не обязательную глубину каталогов:

App\
Http\Controller\
Model\
Repository\

Оператор use — импорт и алиасы

Чтобы не писать FQCN в каждой строке, подключают имена через use:

<?php
namespace App\Http\Controller;

use App\Service\Mailer;
use App\Model\User;
use DateTimeImmutable;

class RegisterController
{
public function __construct(
private Mailer $mailer,
) {}

public function complete(User $user): void
{
$this->mailer->send($user->email, 'Добро пожаловать');
$at = new DateTimeImmutable();
}
}

Алиас — когда короткое имя занято или неудобно:

use App\Legacy\Logger as LegacyLogger;
use Psr\Log\LoggerInterface;

class Worker
{
public function __construct(
private LoggerInterface $logger,
private LegacyLogger $legacy,
) {}
}

Импорт функций и констант (PHP 5.6+):

use function App\Support\config;
use const App\Support\APP_VERSION;

echo config('app.name'), APP_VERSION;

Групповой импорт (PHP 7.0+):

use App\Model\{User, Post, Comment};

Глобальное пространство и встроенные классы

Классы без namespace живут в глобальном пространстве. Встроенные типы (Exception, DateTime, PDO) тоже глобальные. Внутри namespace App\... обращение к ним требует префикса \:

namespace App\Util;

// Ошибка: ищется App\Util\Exception
// throw new Exception('fail');

throw new \Exception('fail'); // верно
$now = new \DateTimeImmutable(); // верно

Связь с файлами — PSR-4

Стандарт PSR-4 задаёт правило: префикс namespace → корневая папка, остаток пути = остаток namespace + имя класса.

FQCNПуть к файлу (при префиксе App\src/)
App\Model\Usersrc/Model/User.php
App\Http\Controller\HomeControllersrc/Http/Controller/HomeController.php

Имя файла совпадает с именем класса, расширение .php. Один класс (или enum, trait, interface) — один файл.

В composer.json проекта:

{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}

После composer dump-autoload подключают единую точку входа:

<?php
require __DIR__ . '/vendor/autoload.php';

use App\Model\User;

$user = new User();

Интерпретатор при первом обращении к User вызывает автозагрузчик Composer, который по карте PSR-4 подключает файл.


Ручная автозагрузка (без Composer)

Для учебных скриптов достаточно spl_autoload_register:

<?php
spl_autoload_register(function (string $class): void {
$prefix = 'App\\';
$baseDir = __DIR__ . '/src/';

if (!str_starts_with($class, $prefix)) {
return;
}

$relative = substr($class, strlen($prefix));
$file = $baseDir . str_replace('\\', '/', $relative) . '.php';

if (is_file($file)) {
require $file;
}
});

В продакшене почти всегда используют Composer: он объединяет автозагрузку проекта и всех зависимостей из vendor/.


Типичные ошибки

СитуацияЧто происходит
Файл не в том каталоге относительно PSR-4Class "App\Model\User" not found
Опечатка в namespace и в useКласс не находится или подключается «чужой»
require старого файла с тем же классомFatal error: Cannot declare class ...
Циклические зависимости классовОшибка при загрузке; рефакторинг через интерфейсы

Нельзя объявлять два класса с одним FQCN. Нельзя смешивать в одном файле несколько именованных классов в строгих проектах (PSR-1 рекомендует один класс на файл).


Практика в веб-приложении

Типичная структура без фреймворка:

project/
public/
index.php ← единственная точка входа для HTTP
src/
Http/
Model/
Service/
vendor/
autoload.php
composer.json

public/index.php только подключает autoload и делегирует маршрутизацию. Вся логика — в классах с namespace App\.... Это совпадает с подходом Laravel и Symfony, где корень приложения отделён от публичной директории.


Что изучить дальше


См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).