mirror of
https://github.com/Vateron-Media/XC_VM.git
synced 2026-04-11 15:39:04 +00:00
docs: add autoloader documentation in English and Russian
Covers: how the autoloader works, adding new classes, cache invalidation, manual registration (addClass), adding new directories, naming rules, duplicate resolution, and debugging. Sidebar links added to both language versions of the Docsify site.
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
|
||||
- 🧰 **Development**
|
||||
- [🖥 CLI Tools & DB Migrations](en-us/development/cli-tools.md)
|
||||
- [⚙️ Autoloader & Class Registration](en-us/development/autoloader.md)
|
||||
|
||||
- 📦 **Additional**
|
||||
- [🎬 Watchfolder](en-us/info/watch_folder.md)
|
||||
|
||||
148
docs/en/development/autoloader.md
Normal file
148
docs/en/development/autoloader.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# Autoloader — Class Registration
|
||||
|
||||
XC_VM uses a custom autoloader (`src/autoload.php`) instead of Composer.
|
||||
Classes are discovered **automatically** — no manual registration required.
|
||||
|
||||
---
|
||||
|
||||
## How It Works
|
||||
|
||||
```
|
||||
Request → autoload.php included
|
||||
│
|
||||
├── Cache file exists?
|
||||
│ YES → load igbinary cache → O(1) lookups
|
||||
│ NO → warmCache(): scan all directories via token_get_all()
|
||||
│ → build ClassName → filePath map
|
||||
│ → persist to tmp/cache/autoload_map
|
||||
│
|
||||
└── Class requested by PHP
|
||||
│
|
||||
├── 1. Explicit classMap (addClass())
|
||||
├── 2. Resolved cache (from file or previous lookup)
|
||||
└── 3. Live directory scan (fallback, cached for next time)
|
||||
```
|
||||
|
||||
## Adding a New Class
|
||||
|
||||
**Just create the file.** That's it.
|
||||
|
||||
Place your PHP file in any registered directory (or its subdirectory):
|
||||
|
||||
| Directory | Purpose |
|
||||
|-----------|---------|
|
||||
| `src/core/` | Framework core (Database, Cache, Auth, Http, Process, etc.) |
|
||||
| `src/domain/` | Business logic (Services, Repositories) |
|
||||
| `src/infrastructure/` | External adapters (DatabaseFactory, CacheReader, Redis) |
|
||||
| `src/streaming/` | Streaming subsystem (Auth, Delivery, Codec, Health) |
|
||||
| `src/modules/` | Optional modules (Plex, Watch, TMDB, Ministra, etc.) |
|
||||
| `src/public/` | Controllers and Views |
|
||||
| `src/includes/` | Legacy code |
|
||||
| `src/includes/libs/` | Third-party libraries |
|
||||
|
||||
### Example
|
||||
|
||||
```php
|
||||
// src/domain/Billing/InvoiceService.php
|
||||
class InvoiceService {
|
||||
public static function generate($userId) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
After creating the file, **delete the cache** so the autoloader rediscovers classes:
|
||||
|
||||
```bash
|
||||
rm -f /home/xc_vm/tmp/cache/autoload_map
|
||||
```
|
||||
|
||||
On the next request, `warmCache()` runs automatically, finds `InvoiceService`, and caches it.
|
||||
|
||||
## Cache Invalidation
|
||||
|
||||
The cache file `tmp/cache/autoload_map` is a binary file (igbinary format).
|
||||
It must be deleted whenever:
|
||||
|
||||
- A new class file is added
|
||||
- A class file is renamed or moved
|
||||
- A class file is deleted
|
||||
|
||||
```bash
|
||||
# Delete manually
|
||||
rm -f /home/xc_vm/tmp/cache/autoload_map
|
||||
|
||||
# Or via PHP
|
||||
XC_Autoloader::clearCache();
|
||||
```
|
||||
|
||||
> **Note:** If a class is requested that isn't in the cache, the autoloader falls back to a live directory scan and caches the result automatically. So the cache only needs to be cleared when files are moved/renamed/deleted — new classes will eventually be found via fallback.
|
||||
|
||||
## Manual Registration (Rare)
|
||||
|
||||
For special cases where a file contains multiple classes or the filename doesn't match the class name:
|
||||
|
||||
```php
|
||||
XC_Autoloader::addClass('DropboxClient', '/home/xc_vm/includes/libs/Dropbox.php');
|
||||
XC_Autoloader::addClass('DropboxException', '/home/xc_vm/includes/libs/Dropbox.php');
|
||||
```
|
||||
|
||||
This is mainly needed for legacy library files that bundle multiple classes in one file (e.g., `iptables.php`, `m3u.php`).
|
||||
|
||||
## Adding a New Source Directory
|
||||
|
||||
Edit `registerDirectories()` in `src/autoload.php`:
|
||||
|
||||
```php
|
||||
private static function registerDirectories() {
|
||||
$base = self::$basePath;
|
||||
|
||||
self::addDirectory($base . 'includes');
|
||||
self::addDirectory($base . 'includes/libs');
|
||||
self::addDirectory($base . 'core');
|
||||
self::addDirectory($base . 'domain');
|
||||
self::addDirectory($base . 'infrastructure');
|
||||
self::addDirectory($base . 'streaming');
|
||||
self::addDirectory($base . 'modules');
|
||||
self::addDirectory($base . 'public');
|
||||
|
||||
// Add your new directory here:
|
||||
self::addDirectory($base . 'my_new_dir');
|
||||
}
|
||||
```
|
||||
|
||||
Then delete the cache.
|
||||
|
||||
## Naming Rules
|
||||
|
||||
| Rule | Example |
|
||||
|------|---------|
|
||||
| File name **must** match class name | `InvoiceService.php` → `class InvoiceService` |
|
||||
| One class per file (recommended) | Multi-class files need `addClass()` |
|
||||
| PascalCase | `StreamService`, `DatabaseHandler` |
|
||||
| No namespaces | `class StreamService { }` — no `namespace` keyword |
|
||||
| No `declare(strict_types=1)` | Project convention |
|
||||
|
||||
## Duplicate Class Names
|
||||
|
||||
If two files define the same class name, **first-found wins** based on directory scan order. This is fragile — avoid duplicate names. Use prefixed names instead:
|
||||
|
||||
```
|
||||
✗ public/Controllers/Admin/PlexController.php ← conflict
|
||||
✗ modules/plex/PlexController.php ← conflict
|
||||
|
||||
✓ public/Controllers/Admin/AdminPlexController.php ← unique
|
||||
✓ modules/plex/PlexController.php ← unique
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
```php
|
||||
// See all registered directories
|
||||
print_r(XC_Autoloader::getDirectories());
|
||||
|
||||
// See explicit class map
|
||||
print_r(XC_Autoloader::getClassMap());
|
||||
|
||||
// Force full rescan
|
||||
XC_Autoloader::clearCache();
|
||||
XC_Autoloader::warmCache();
|
||||
```
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
- 🧰 **Разработка**
|
||||
- [🖥 CLI-инструменты и миграции БД](ru-ru/development/cli-tools.md)
|
||||
- [⚙️ Автозагрузчик и регистрация классов](ru-ru/development/autoloader.md)
|
||||
|
||||
- 📦 **Дополнительно**
|
||||
- [🎬 Watchfolder](ru-ru/info/watch_folder.md)
|
||||
|
||||
148
docs/ru/development/autoloader.md
Normal file
148
docs/ru/development/autoloader.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# Автозагрузчик — Регистрация классов
|
||||
|
||||
XC_VM использует собственный автозагрузчик (`src/autoload.php`) вместо Composer.
|
||||
Классы обнаруживаются **автоматически** — ручная регистрация не нужна.
|
||||
|
||||
---
|
||||
|
||||
## Как это работает
|
||||
|
||||
```
|
||||
Запрос → подключается autoload.php
|
||||
│
|
||||
├── Файл кэша существует?
|
||||
│ ДА → загрузить igbinary кэш → O(1) поиск
|
||||
│ НЕТ → warmCache(): сканировать все директории через token_get_all()
|
||||
│ → построить карту ClassName → filePath
|
||||
│ → сохранить в tmp/cache/autoload_map
|
||||
│
|
||||
└── PHP запрашивает класс
|
||||
│
|
||||
├── 1. Явная карта (addClass())
|
||||
├── 2. Кэш (файловый или из предыдущего поиска)
|
||||
└── 3. Живой поиск по директориям (fallback, кэшируется)
|
||||
```
|
||||
|
||||
## Добавление нового класса
|
||||
|
||||
**Просто создайте файл.** Это всё.
|
||||
|
||||
Поместите PHP-файл в любую зарегистрированную директорию (или её поддиректорию):
|
||||
|
||||
| Директория | Назначение |
|
||||
|-----------|---------|
|
||||
| `src/core/` | Ядро фреймворка (Database, Cache, Auth, Http, Process и т.д.) |
|
||||
| `src/domain/` | Бизнес-логика (Services, Repositories) |
|
||||
| `src/infrastructure/` | Внешние адаптеры (DatabaseFactory, CacheReader, Redis) |
|
||||
| `src/streaming/` | Стриминг-подсистема (Auth, Delivery, Codec, Health) |
|
||||
| `src/modules/` | Опциональные модули (Plex, Watch, TMDB, Ministra и т.д.) |
|
||||
| `src/public/` | Контроллеры и Views |
|
||||
| `src/includes/` | Legacy-код |
|
||||
| `src/includes/libs/` | Сторонние библиотеки |
|
||||
|
||||
### Пример
|
||||
|
||||
```php
|
||||
// src/domain/Billing/InvoiceService.php
|
||||
class InvoiceService {
|
||||
public static function generate($userId) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
После создания файла **удалите кэш**, чтобы автозагрузчик обнаружил новые классы:
|
||||
|
||||
```bash
|
||||
rm -f /home/xc_vm/tmp/cache/autoload_map
|
||||
```
|
||||
|
||||
При следующем запросе `warmCache()` запустится автоматически, найдёт `InvoiceService` и закэширует.
|
||||
|
||||
## Инвалидация кэша
|
||||
|
||||
Файл кэша `tmp/cache/autoload_map` — бинарный файл (формат igbinary).
|
||||
Его нужно удалять когда:
|
||||
|
||||
- Добавлен новый файл с классом
|
||||
- Файл с классом переименован или перемещён
|
||||
- Файл с классом удалён
|
||||
|
||||
```bash
|
||||
# Удалить вручную
|
||||
rm -f /home/xc_vm/tmp/cache/autoload_map
|
||||
|
||||
# Или через PHP
|
||||
XC_Autoloader::clearCache();
|
||||
```
|
||||
|
||||
> **Примечание:** Если запрошен класс, которого нет в кэше, автозагрузчик делает живой поиск по директориям и кэширует результат. Поэтому кэш нужно сбрасывать только при перемещении/переименовании/удалении — новые классы будут найдены через fallback.
|
||||
|
||||
## Ручная регистрация (редко)
|
||||
|
||||
Для особых случаев когда файл содержит несколько классов или имя файла не совпадает с именем класса:
|
||||
|
||||
```php
|
||||
XC_Autoloader::addClass('DropboxClient', '/home/xc_vm/includes/libs/Dropbox.php');
|
||||
XC_Autoloader::addClass('DropboxException', '/home/xc_vm/includes/libs/Dropbox.php');
|
||||
```
|
||||
|
||||
Это нужно в основном для legacy-библиотек с несколькими классами в одном файле (например, `iptables.php`, `m3u.php`).
|
||||
|
||||
## Добавление новой директории
|
||||
|
||||
Отредактируйте `registerDirectories()` в `src/autoload.php`:
|
||||
|
||||
```php
|
||||
private static function registerDirectories() {
|
||||
$base = self::$basePath;
|
||||
|
||||
self::addDirectory($base . 'includes');
|
||||
self::addDirectory($base . 'includes/libs');
|
||||
self::addDirectory($base . 'core');
|
||||
self::addDirectory($base . 'domain');
|
||||
self::addDirectory($base . 'infrastructure');
|
||||
self::addDirectory($base . 'streaming');
|
||||
self::addDirectory($base . 'modules');
|
||||
self::addDirectory($base . 'public');
|
||||
|
||||
// Добавьте новую директорию:
|
||||
self::addDirectory($base . 'my_new_dir');
|
||||
}
|
||||
```
|
||||
|
||||
Затем удалите кэш.
|
||||
|
||||
## Правила именования
|
||||
|
||||
| Правило | Пример |
|
||||
|---------|--------|
|
||||
| Имя файла **должно** совпадать с именем класса | `InvoiceService.php` → `class InvoiceService` |
|
||||
| Один класс на файл (рекомендуется) | Файлы с несколькими классами требуют `addClass()` |
|
||||
| PascalCase | `StreamService`, `DatabaseHandler` |
|
||||
| Без namespace | `class StreamService { }` — без ключевого слова `namespace` |
|
||||
| Без `declare(strict_types=1)` | Конвенция проекта |
|
||||
|
||||
## Дублирование имён классов
|
||||
|
||||
Если два файла определяют одинаковое имя класса, **побеждает первый найденный** по порядку сканирования директорий. Это хрупко — избегайте дубликатов. Используйте префиксы:
|
||||
|
||||
```
|
||||
✗ public/Controllers/Admin/PlexController.php ← конфликт
|
||||
✗ modules/plex/PlexController.php ← конфликт
|
||||
|
||||
✓ public/Controllers/Admin/AdminPlexController.php ← уникально
|
||||
✓ modules/plex/PlexController.php ← уникально
|
||||
```
|
||||
|
||||
## Отладка
|
||||
|
||||
```php
|
||||
// Все зарегистрированные директории
|
||||
print_r(XC_Autoloader::getDirectories());
|
||||
|
||||
// Явная карта классов
|
||||
print_r(XC_Autoloader::getClassMap());
|
||||
|
||||
// Принудительный полный пересканирование
|
||||
XC_Autoloader::clearCache();
|
||||
XC_Autoloader::warmCache();
|
||||
```
|
||||
Reference in New Issue
Block a user