Что делает autoloading
Autoloading в PHP — это механизм, который загружает файл с классом в тот момент, когда код впервые обращается к ещё не объявленному class-like имени: классу, интерфейсу, trait или enum. Он не заменяет Неймспейсы и use: namespace даёт имя, use сокращает это имя внутри файла, а autoloader отвечает за вопрос «из какого .php-файла взять объявление этого имени?».
Без автозагрузки большой OOP-проект быстро превращается в список require_once в начале каждого entrypoint. С автозагрузкой код обычно начинается с одного bootstrap-файла:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use App\Billing\Invoice;
$invoice = new Invoice(1500);Когда PHP доходит до new Invoice(...), имя уже развёрнуто в App\Billing\Invoice. Если такого класса ещё нет в памяти, PHP вызывает зарегистрированные autoloader-функции. В современных проектах почти всегда используется Composer autoloader.
flowchart TD
A["Код обращается к App\\Billing\\Invoice"] --> B{"Класс уже объявлен?"}
B -- "да" --> C["PHP использует класс"]
B -- "нет" --> D["PHP вызывает зарегистрированные autoloader'ы"]
D --> E["Composer читает PSR-4 mapping: App\\ => src/"]
E --> F["App\\Billing\\Invoice -> src/Billing/Invoice.php"]
F --> G{"Файл найден и объявил нужный FQCN?"}
G -- "да" --> C
G -- "нет" --> H["Следующий autoloader или ошибка Class not found"]spl_autoload_register
Низкоуровневый API языка — spl_autoload_register(). Он регистрирует callback, который получает полное имя класса и может подключить нужный файл.
<?php
declare(strict_types=1);
spl_autoload_register(function (string $class): void {
$prefix = 'App\\';
$baseDir = __DIR__ . '/src/';
if (!str_starts_with($class, $prefix)) {
return;
}
$relativeClass = substr($class, strlen($prefix));
$file = $baseDir . str_replace('\\', '/', $relativeClass) . '.php';
if (is_file($file)) {
require $file;
}
});
$service = new App\Billing\InvoiceService();Это рабочая иллюстрация, но в обычном проекте такой код писать не нужно. Composer уже делает это надёжнее: поддерживает несколько правил автозагрузки, пакеты из vendor/, autoload-dev, classmap, оптимизацию для продакшна и edge cases, которые легко забыть в самописном загрузчике.
Важно: autoloader — это «последний шанс» перед ошибкой «class not found». Он не должен выполнять бизнес-логику, ходить в базу, менять глобальное состояние или бросать исключения. По стандарту PSR-4 autoloader не должен выбрасывать исключения и поднимать ошибки: если он не нашёл файл, он просто уступает место следующему autoloader.
PSR-4: имя класса как путь к файлу
PSR-4 — это стандарт PHP-FIG, который описывает, как сопоставлять fully qualified class name с файловым путём. Он не является частью синтаксиса PHP, но стал основным соглашением экосистемы: Composer, IDE, фреймворки и статические анализаторы ожидают именно такую структуру.
Минимальная идея такая:
FQCN: App\Catalog\Product
Namespace prefix: App\
Base directory: src/
File: src/Catalog/Product.phpА файл выглядит так:
<?php
declare(strict_types=1);
namespace App\Catalog;
final class Product
{
public function __construct(
public readonly string $sku,
public readonly string $name,
) {}
}PSR-4 использует несколько правил. У класса должно быть полное имя с верхним namespace, часто его называют vendor namespace: App, Symfony, Psr, VendorName. Начальная часть имени — namespace prefix — сопоставляется с одной или несколькими base directory. Оставшиеся subnamespace превращаются в поддиректории. Последний сегмент имени класса становится именем файла с расширением .php.
Регистр важен. App\Catalog\Product должен лежать в src/Catalog/Product.php, а не в src/catalog/product.php. На macOS такая ошибка может пройти незаметно из-за особенностей файловой системы, а на Linux-сервере сломать деплой. Это одна из причин, почему CI, линтеры и автоматические проверки полезны даже для небольших PHP-проектов.
Composer autoload
В Composer правило PSR-4 задаётся в composer.json:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}
}Двойной обратный слеш здесь нужен из-за JSON: строка "App\\" означает реальный PHP-префикс App\. После изменения секции autoload нужно пересобрать файлы автозагрузки:
composer dump-autoloadили, если Composer установлен локально как composer.phar:
php composer.phar dump-autoloadComposer генерирует vendor/autoload.php и вспомогательные файлы внутри vendor/composer/. Именно vendor/autoload.php подключают из entrypoint приложения, тестов, консольных скриптов или фронт-контроллера. Связь с Composer, Packagist и composer.json прямая: тот же файл описывает зависимости проекта и правила, по которым собственный код становится доступен без ручных require.
Для продакшна часто используют оптимизацию:
composer dump-autoload --optimize
# коротко:
composer dump-autoload -oОптимизированный autoloader превращает PSR-0/PSR-4-правила в classmap там, где это возможно, чтобы быстрее находить классы. Более жёсткий режим --classmap-authoritative говорит Composer искать только в classmap; он может быть полезен в стабильной продакшн-сборке, но неудобен во время разработки, когда файлы часто добавляются и переименовываются.
Что автозагружается, а что нет
PSR-4 относится к class-like сущностям: class, interface, trait, enum. Поэтому Enum в PHP автозагружаются так же, как классы:
namespace App\Order;
enum OrderStatus: string
{
case Draft = 'draft';
case Paid = 'paid';
}Функции и константы сами по себе через PSR-4 не автозагружаются. Если проекту нужны глобальные helper-функции, Composer поддерживает режим files, но это другой механизм: указанные файлы подключаются при загрузке autoloader, а не по первому вызову функции.
{
"autoload": {
"psr-4": {
"App\\": "src/"
},
"files": [
"src/Support/helpers.php"
]
}
}Используйте files аккуратно. В OOP-коде чаще лучше вынести поведение в классы, сервисы или value objects, особенно если с этим кодом будут работать PHPDoc, generics и статический анализ.
Типичные поломки
Самая частая ошибка — namespace в файле не совпадает с путём. Например, файл лежит в src/Billing/Invoice.php, но внутри написано namespace App\Billings;. Composer может честно искать App\Billing\Invoice, открыть ожидаемый файл и всё равно не найти нужный класс, потому что в файле объявлено другое имя.
Вторая ошибка — забыли composer dump-autoload после изменения composer.json. Новые классы в PSR-4-директории обычно находятся без пересборки, но новые namespace mappings, autoload-dev, files и classmap требуют обновить автозагрузчик.
Третья — конфликт имён из-за неаккуратного use. Autoloading не решает смысловые конфликты: если в файле импортирован не тот User, PHP загрузит именно тот класс, который указан именем. Здесь помогают явные импорты, alias и стиль из PSR-1, PSR-12 и стиль кода.
Четвёртая — побочные эффекты в файлах классов. Файл, который загружается autoloader, должен в основном объявлять класс. Не стоит печатать HTML, читать $_POST, запускать миграции или создавать соединение с БД прямо на верхнем уровне файла. Иначе простой new App\Service\ReportBuilder() внезапно запускает невидимую работу.
Практическая модель в голове
Хороший PHP-проект держит три слоя отдельно. Неймспейсы и use задают имена и короткие ссылки в коде. PSR-4 задаёт соглашение «имя → путь». Composer генерирует реальный autoloader, который PHP вызывает при первом обращении к классу.
Если класс не находится, проверяйте в таком порядке: точное FQCN в коде, namespace внутри файла, путь и регистр директорий, правило autoload.psr-4 в composer.json, запуск composer dump-autoload, подключение vendor/autoload.php в entrypoint. Такой порядок быстрее, чем хаотично добавлять require_once и ломать архитектуру проекта.
См. также
- Неймспейсы и use — как PHP разворачивает короткие, относительные и абсолютные имена.
- Composer, Packagist и composer.json — где описываются зависимости и секция
autoload. - Классы, объекты и видимость — что именно загружает autoloader: классы и их объявления.
- Enum в PHP — enum тоже class-like сущность и подчиняется тем же правилам автозагрузки.
- Атрибуты и Reflection — как читать загруженные классы, методы и атрибуты во время выполнения.
- PHPDoc, generics и статический анализ — почему корректные FQCN и autoload rules важны для PHPStan/Psalm и IDE.
- PSR-1, PSR-12 и стиль кода — оформление файлов,
namespace,useи class declarations.