Автозагрузка в PHP: рабочие приёмы через Composer и PSR-4
Как настроить автозагрузку классов в PHP-проекте: PSR-4 через Composer, classmap для чужого кода, files для хелперов. Что выбрать под каждую задачу и чем платишь за каждый вариант.

Вы добавили новый класс в проект, обновили use, запускаете — Fatal error: Uncaught Error: Class "App\Service\Invoice" not found. Файл на месте, namespace правильный, но PHP его не видит. Почти всегда причина одна: автозагрузка настроена не так, как разложены файлы, или composer-карту забыли пересобрать. Разберём, какие механизмы автозагрузки существуют в PHP 8.x, что выбрать под конкретную задачу и где каждый вариант подводит.
Что вообще делает автозагрузчик
Когда PHP встречает имя класса, которого ещё нет в памяти, он по очереди вызывает функции, зарегистрированные через spl_autoload_register(). Каждая получает полное имя класса строкой и должна подключить нужный файл. Первая, что нашла файл и подключила его, завершает поиск.
Ручной require для каждого класса не масштабируется: сотни файлов, порядок подключения, дубли. Автозагрузка снимает это — файл подключается ровно тогда, когда класс впервые понадобился, и ни секундой раньше.
Функция __autoload() из старого PHP удалена в 8.0. Если наткнётесь на неё в древнем коде — это единственный автозагрузчик на весь процесс, работать с ним смысла нет. Всё современное строится на spl_autoload_register, который допускает несколько обработчиков в очереди.
Четыре рабочих подхода
На практике вы выбираете между четырьмя вариантами. Три из них — режимы Composer, один — ручная регистрация без Composer вообще.
PSR-4 через Composer — база для 95% проектов
PSR-4* связывает префикс namespace с директорией. Правило простое: часть имени класса после префикса превращается в путь, разделители \ становятся /, в конце добавляется .php.
В composer.json:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Класс App\Service\Invoice при таком правиле ищется в src/Service/Invoice.php. После правки блока autoload обязательно выполните:
composer dump-autoload
В точке входа подключаете один файл:
<?php
// public/index.php
require __DIR__ . '/../vendor/autoload.php';
use App\Service\Invoice;
$invoice = new Invoice();
Цена подхода: вы обязаны держать структуру файлов в строгом соответствии с namespace. Переименовали директорию, но забыли namespace в классе — получите Class not found, хотя файл на диске есть.
classmap — для кода, который не следует PSR-4
Иногда в проекте лежит библиотека или легаси-модуль, где имена файлов и классов не подчиняются никакому стандарту: class-invoice-builder.php с классом Invoice_Builder внутри (привычная история для плагинов WordPress). PSR-4 такое не разберёт.
{
"autoload": {
"classmap": [
"legacy/",
"lib/old-parser.php"
]
}
}
При composer dump-autoload Composer прочитает все указанные файлы и директории, найдёт в них объявления классов и построит прямую карту «имя класса → путь». Работает независимо от расположения.
Цена: карта статична. Добавили новый класс в legacy/ — старая карта его не знает, пока не пересоберёте. В разработке это неудобно, поэтому classmap держат для стабильного кода, который не трогают.
files — не про классы
Раздел files подключает файлы безусловно при каждом запросе, ещё до любой автозагрузки. Он нужен для того, что нельзя загрузить лениво: глобальные функции-хелперы, константы, полифилы.
{
"autoload": {
"files": [
"src/helpers.php"
]
}
}
Классы сюда не кладут. Файл из files грузится всегда, даже если функции из него в этом запросе не вызвали — вы теряете весь смысл ленивой загрузки.
spl_autoload_register вручную — когда Composer недоступен
На хостинге без Composer или в мелком скрипте автозагрузчик пишется руками:
<?php
// autoload.php
spl_autoload_register(function (string $class): void {
$prefix = 'App\\';
$baseDir = __DIR__ . '/src/';
// Класс не из нашего namespace — пропускаем, пусть ищут другие
if (strncmp($prefix, $class, strlen($prefix)) !== 0) {
return;
}
$relative = substr($class, strlen($prefix));
$file = $baseDir . str_replace('\\', '/', $relative) . '.php';
if (is_file($file)) {
require $file;
}
});
Это ручная реализация той же логики PSR-4. Ключевой момент — ранний return для чужих классов: если ваш обработчик не относится к искомому классу, он ничего не должен делать и не бросать исключение, иначе сломает остальную очередь автозагрузчиков.
Автозагрузчик, который бросает исключение на «не свой» класс, — самая частая причина того, что чужая библиотека в проекте перестаёт загружаться без внятной ошибки.
Что выбирать под задачу
| Подход | Когда | Чем платишь |
|---|---|---|
| psr-4 | ваш код, структура файлов = namespace | жёсткое соответствие путей и имён |
| classmap | легаси и библиотеки без стандарта | пересборка карты при каждом новом классе |
| files | функции, константы, полифилы | грузится всегда, лениво нельзя |
| ручной spl_autoload_register | нет Composer | сами следите за очередью и краевыми случаями |
Правило по умолчанию: новый код — PSR-4. Всё остальное — по необходимости. Инвалидация OPcache при деплое — отдельная тема, здесь её не разбираем.
Оптимизация карты для прода
В режиме PSR-4 на каждый новый класс PHP собирает путь и проверяет файл на диске через is_file. На проде эти проверки — лишние обращения к файловой системе. Composer умеет свернуть PSR-4 в статическую classmap:
# оптимизированная карта для боевого окружения
composer dump-autoload --optimize
# то же плюс запрет искать классы вне карты — самый строгий режим
composer dump-autoload --optimize --classmap-authoritative
Флаг --optimize (короткий -o) один раз сканирует все PSR-4 директории и строит прямую карту. Класс ищется одной операцией по массиву вместо обращения к диску.
Флаг --classmap-authoritative идёт дальше: если класса нет в карте, Composer даже не проверяет диск, а сразу считает, что класса не существует. Быстрее всего, но с одним подводным камнем — классы, сгенерированные во время выполнения или добавленные без пересборки карты, перестают находиться. На проде это то, что нужно; в разработке — источник загадочных «класс есть, но не грузится».
Точные названия и поведение флагов проверяйте в документации вашей версии Composer перед деплоем — набор ключей между мажорными версиями менялся.
Если не получилось
Class "App\Service\Invoice" not found, а файл на месте. Сверьте три вещи: namespace внутри файла точноApp\Service, имя класса совпадает с именем файла с точностью до регистра, путь соответствует правилу PSR-4. На Linux файловая система чувствительна к регистру —invoice.phpиInvoice.phpдля неё разные файлы, и это ломает автозагрузку, которая на macOS или Windows работала.- Добавили класс, но он не находится. Если используете classmap или собрали карту через
--optimize— выполнитеcomposer dump-autoloadзаново. Оптимизированная карта не знает о новых файлах. - Всё сломалось после деплоя, локально работало. Частая причина —
--classmap-authoritativeна проде и класс, которого не было в карте на момент сборки. Пересоберите карту или временно уберите флаг, чтобы подтвердить причину. vendor/autoload.phpне найден. Не выполненcomposer installв окружении, либо каталогvendorисключён из деплоя. Проверьте, что зависимости ставятся на целевом сервере.- Хелпер-функция не определена. Файл с функциями попал в PSR-4 вместо
files. Функции автозагрузчиком не подключаются — только классы, интерфейсы, трейты и енумы.
Что настроить дальше
Разделите автозагрузку на два блока: autoload для боевого кода и autoload-dev для тестов и фикстур — тогда тестовые классы не попадут в оптимизированную карту прода. В пайплайне деплоя добавьте composer dump-autoload --optimize --classmap-authoritative отдельным шагом. На проде включите OPcache — без него ленивая загрузка всё равно упирается в парсинг файлов на каждом запросе. Смотрите на число попаданий в OPcache и на время автозагрузки в профилировщике (Blackfire, Xdebug): если оно заметно на фоне остального — это сигнал перейти на authoritative-карту.
Задачи: математика, физика, химия: Разбор задачи по шагам с проверкой и похожей задачей
Спросить за 10 ₽Источники: PSR-4: Autoloader — PHP-FIG, Composer — Autoloading (documentation)
Частые вопросы
У меня на локали работает, а на сервере класс не находится. Почему?
Нужно ли вызывать composer dump-autoload после каждого нового класса?
Работает ли автозагрузка в PHP 8.x без Composer?
Можно ли загружать функции через автозагрузку?
Опасно ли включать --classmap-authoritative на проде?
Что лучше для скорости — PSR-4 или classmap?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.