Автозагрузка

Обзор

Автозагрузка — это концепция в PHP, при которой вы указываете каталог или каталоги для загрузки классов. Это гораздо полезнее, чем использование require или include для загрузки классов. Это также требование для использования пакетов Composer.

Правильная настройка автозагрузки важна и для разработки с помощью ИИ: агенты размещают файлы там, куда указывает пространство имён. Если регистр папок и регистр пространства имён не совпадают, на Linux появляются ошибки «класс не найден», даже если на Mac с регистронезависимой файловой системой всё «работало».

Понимание

По умолчанию все классы Flight автоматически загружаются благодаря Composer. Для ваших классов приложения есть два распространённых подхода:

  1. Composer PSR-4 (используется в официальном скелетоне): сопоставьте префикс пространства имён с каталогом в composer.json, затем выполните composer dump-autoload.
  2. Flight::path(): укажите загрузчику Flight каталоги (удобно для простых приложений или когда вы не используете Composer для кода приложения).

Использование автозагрузчика значительно упрощает ваш код. Вместо стены из include / require в начале каждого файла классы загружаются при первом использовании.

Чувствительность к регистру (прочитайте дважды)

Пространства имён должны соответствовать структуре каталогов и регистру букв в этих каталогах.

Работает Ломается на Linux
App\Controller\HomeControllerapp/Controller/HomeController.php App\Controller\… с каталогом app/controllers/
app\controllers\MyControllerapp/controllers/MyController.php Смешивание App\ с нижним регистром controllers

Пространства имён PHP не чувствительны к регистру в некоторых контекстах, но Composer и файловая система — нет. Официальный скелетон придерживается следующих стандартов:

  • Composer: "App\\": "app/"
  • Каталоги: Controller, Middleware, Model, Utils (PascalCase), а не controllers / middlewares

В старой документации и примерах сообщества иногда использовался нижний регистр app\controllers. Это по-прежнему работает, если ваши каталоги в нижнем регистре, — но новые проекты на скелетоне используют App\ + каталоги в PascalCase. Выберите одно соглашение для проекта и придерживайтесь его, чтобы люди и ИИ-инструменты не придумывали вторую структуру.

Скелетон (рекомендуется для новых проектов)

После composer create-project flightphp/skeleton код приложения автозагружается через Composer — Flight::path() для классов App\ не требуется:

{
  "autoload": {
    "psr-4": {
      "App\\": "app/"
    }
  }
}
// app/Controller/HomeController.php
namespace App\Controller;

use flight\Engine;

class HomeController
{
    protected Engine $app;

    public function __construct(Engine $app)
    {
        $this->app = $app;
    }

    public function index(): void
    {
        $this->app->render('welcome', ['message' => 'Hello!']);
    }
}
// app/config/routes.php — Dice сопоставляет App\Controller\… через контейнер
$router->get('/', [HomeController::class, 'index']);

Смотрите Установка для полного дерева каталогов и ИИ и опыт разработчика о том, как AGENTS.md документирует эту структуру для помощников по коду.

Базовое использование (Flight::path())

Предположим, у нас есть следующее дерево каталогов:

# Пример пути
/home/user/project/my-flight-project/
├── app
│   ├── cache
│   ├── config
│   ├── controllers - содержит контроллеры этого проекта
│   ├── translations
│   ├── UTILS - содержит классы только для этого приложения (здесь намеренно все заглавные буквы для примера позже)
│   └── views
└── public
    └── css
    └── js
    └── index.php

Вы могли заметить, что это похоже на типичное дерево приложения (сам сайт документации использует структурированную раскладку). Нижний регистр controllers здесь — допустимый выбор; просто это не текущее значение по умолчанию для скелетона.

Вы можете указать каждый каталог для загрузки следующим образом:


/**
 * public/index.php
 */

// Добавляем путь в автозагрузчик
Flight::path(__DIR__.'/../app/controllers/');
Flight::path(__DIR__.'/../app/utils/');


/**
 * app/controllers/MyController.php
 */

// пространство имён не требуется

// Все автозагружаемые классы рекомендуется именовать в Pascal Case (каждое слово с заглавной буквы, без пробелов)
class MyController {

    public function index() {
        // что-то делаем
    }
}

Пространства имён с Flight::path()

Если у вас есть пространства имён, это реализуется очень легко. Вам следует использовать метод Flight::path() для указания корневого каталога (не корня документа и не папки public/) вашего приложения.


/**
 * public/index.php
 */

// Добавляем путь в автозагрузчик
Flight::path(__DIR__.'/../');

Вот как может выглядеть ваш контроллер. Посмотрите на пример ниже, но обратите внимание на комментарии — там важная информация.

/**
 * app/controllers/MyController.php
 */

// пространства имён обязательны
// пространства имён совпадают со структурой каталогов
// пространства имён должны совпадать по регистру со структурой каталогов
// пространства имён и каталоги не могут содержать подчёркивания (если не задано Loader::setV2ClassLoading(false))
namespace app\controllers;

// Все автозагружаемые классы рекомендуется именовать в Pascal Case (каждое слово с заглавной буквы, без пробелов)
// Начиная с 3.7.2, вы можете использовать Pascal_Snake_Case для имён классов, выполнив Loader::setV2ClassLoading(false);
class MyController {

    public function index() {
        // что-то делаем
    }
}

Если вы хотите автозагрузить класс в вашем каталоге utils, вы делаете в основном то же самое:


/**
 * app/UTILS/ArrayHelperUtil.php
 */

// пространство имён должно соответствовать структуре каталогов и регистру (обратите внимание, что каталог UTILS заглавными буквами
//     как в дереве файлов выше)
namespace app\UTILS;

class ArrayHelperUtil {

    public function changeArrayCase(array $array) {
        // что-то делаем
    }
}

Пространство имён в стиле скелетона (те же правила, другой регистр)

/**
 * app/Controller/MyController.php
 */
namespace App\Controller;

class MyController {
    // ...
}

Правило не изменилось — изменился только выбранный скелетоном регистр каталогов/пространств имён. Какой бы регистр вы ни использовали для папок, строка namespace должна ему соответствовать.

Подчёркивания в именах классов

Начиная с 3.7.2, вы можете использовать Pascal_Snake_Case для имён классов, выполнив Loader::setV2ClassLoading(false);. Это позволяет использовать подчёркивания в именах классов. Это не рекомендуется, но доступно тем, кому это нужно.

use flight\core\Loader;

/**
 * public/index.php
 */

// Добавляем путь в автозагрузчик
Flight::path(__DIR__.'/../app/controllers/');
Flight::path(__DIR__.'/../app/utils/');
Loader::setV2ClassLoading(false);

/**
 * app/controllers/My_Controller.php
 */

// пространство имён не требуется

class My_Controller {

    public function index() {
        // что-то делаем
    }
}

Смотрите также

Устранение неполадок

  • Если вы не можете понять, почему ваши классы с пространствами имён не находятся, запомните: при использовании Flight::path() указывайте на корень проекта (или правильную базу для вашего пространства имён), а не только на вложенную папку, которую вы забыли отразить в пространстве имён.
  • При использовании Composer PSR-4 выполните composer dump-autoload после изменения сопоставлений в composer.json.
  • В CI на Linux или в продакшене неправильный регистр папки — очень распространённый сбой «у меня работает».

Класс не найден (автозагрузка не работает)

Причин этой проблемы может быть несколько. Ниже приведены некоторые примеры.

Неправильное имя файла

Самая распространённая причина — имя класса не совпадает с именем файла.

Если у вас есть класс с именем MyClass, файл должен называться MyClass.php. Если у вас есть класс MyClass, а файл называется myclass.php, автозагрузчик не сможет его найти.

Неправильное пространство имён или регистр папки

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

// ...код...

// если ваш MyController находится в app/Controller (скелетон) и пространство имён App\Controller
// это не будет работать:
Flight::route('/hello', 'MyController->hello');

// Стиль скелетона:
use App\Controller\MyController;
Flight::route('/hello', [ MyController::class, 'hello' ]);

// Старая раскладка с нижним регистром (только если ваши папки на самом деле app/controllers):
use app\controllers\MyController;
Flight::route('/hello', [ MyController::class, 'hello' ]);
// или полностью определённое имя:
Flight::route('/hello', [ 'App\Controller\MyController', 'hello' ]);

path() не определён (код приложения без Composer)

Если вы полагаетесь на Flight::path() вместо Composer для классов приложения, определите путь до маршрутов, которые ссылаются на эти классы (часто в начале загрузчика / public/index.php):

// Добавляем путь в автозагрузчик (корень проекта для приложений с пространствами имён)
Flight::path(__DIR__.'/../');

Официальный скелетон в основном использует Composer PSR-4 для App\, поэтому обычно вам не понадобится Flight::path() для контроллеров и моделей там.

История изменений

  • Документация — Описание скелетона App\ + каталогов в PascalCase и проблем с регистром для людей и ИИ-инструментов.
  • v3.7.2 — Вы можете использовать Pascal_Snake_Case для имён классов, выполнив Loader::setV2ClassLoading(false);
  • v2.0 — Добавлена функция автозагрузки.