Files
XC_VM/docs/en/development/autoloader.md
T

4.5 KiB

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

Example

// src/domain/Billing/InvoiceService.php
class InvoiceService {
    public static function generate($userId) { ... }
}

After creating the file, delete the cache so the autoloader rediscovers classes:

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
# 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:

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:

private static function registerDirectories() {
    $base = self::$basePath;

    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

// 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();