Autoloading en PHP: spl_autoload_register y el estándar PSR-4

El autoloading en PHP permite cargar clases automáticamente cuando se usan por primera vez, sin necesidad de escribir un require_once por cada fichero. La función spl_autoload_register() registra una o varias funciones de carga que PHP ejecuta en cadena cuando encuentra una clase desconocida. El estándar PSR-4 establece la convención más extendida, y Composer la implementa automáticamente.

spl_autoload_register() básico

Antes de PSR-4 y Composer era habitual escribir un autoloader propio. spl_autoload_register() registra un callable que recibe el nombre completo de la clase (con namespace) y se encarga de hacer el require del fichero correspondiente.

<?php
spl_autoload_register(function (string $claseCompleta): void {
    // Convertir el separador de namespace en separador de directorio
    $ruta = str_replace('\', DIRECTORY_SEPARATOR, $claseCompleta) . '.php';

    if (file_exists($ruta)) {
        require $ruta;
    }
});

// Ahora esta línea carga automáticamente src/App/Modelos/Usuario.php
$usuario = new AppModelosUsuario(1, 'Ana', '[email protected]');
?>

Autoloader PSR-4 paso a paso

PSR-4 establece que el namespace raíz de un paquete se mapea a un directorio base. El resto del namespace corresponde a subdirectorios. Un autoloader PSR-4 completo necesita conocer ese mapeo para construir la ruta correcta.

<?php
/**
 * Autoloader PSR-4 minimal.
 *
 * @param array<string,string> $prefijos  Mapa namespace_prefix => directorio_base
 */
function registrarAutoloaderPSR4(array $prefijos): void
{
    spl_autoload_register(function (string $claseCompleta) use ($prefijos): void {
        foreach ($prefijos as $prefijo => $dirBase) {
            $longitud = strlen($prefijo);

            // ¿La clase pertenece a este prefijo?
            if (strncmp($claseCompleta, $prefijo, $longitud) !== 0) {
                continue;
            }

            // Construir la ruta relativa desde el namespace raíz
            $claseRelativa = substr($claseCompleta, $longitud);
            $ruta = rtrim($dirBase, DIRECTORY_SEPARATOR)
                . DIRECTORY_SEPARATOR
                . str_replace('\', DIRECTORY_SEPARATOR, $claseRelativa)
                . '.php';

            if (file_exists($ruta)) {
                require $ruta;
                return;
            }
        }
    });
}

// Registrar los namespaces del proyecto
registrarAutoloaderPSR4([
    'App\'  => __DIR__ . '/src/',
    'Tests\' => __DIR__ . '/tests/',
]);

// Ahora se puede usar cualquier clase bajo App\ sin require_once
use AppServiciosFacturaGeneradorPDF;
$pdf = new GeneradorPDF();
?>

PSR-0 vs PSR-4

PSR-0 fue el primer estándar de autoloading; PSR-4 lo sustituyó porque PSR-0 generaba rutas más largas y no permitía estructuras de directorios tan flexibles. PSR-0 está obsoleto desde 2014 y solo aparece en proyectos heredados.

<?php
// PSR-0 (obsoleto): los guiones bajos en el nombre de clase se traducen a /
// Vendor_Paquete_Clase => Vendor/Paquete/Clase.php
// App_Modelos_Usuario  => App/Modelos/Usuario.php (con subdirectorios redundantes)

// PSR-4 (actual): el namespace raíz puede mapearse a cualquier directorio
// AppModelosUsuario   => src/Modelos/Usuario.php  (más limpio, sin repetición)
?>

El autoloader de Composer

Composer genera automáticamente un autoloader optimizado en vendor/autoload.php a partir de la configuración de composer.json. Solo hay que hacer un require de ese fichero y todas las clases del proyecto y sus dependencias estarán disponibles.

<?php
// composer.json
// {
//   "autoload": {
//     "psr-4": {
//       "App\": "src/"
//     }
//   },
//   "autoload-dev": {
//     "psr-4": {
//       "Tests\": "tests/"
//     }
//   }
// }

// Tras ejecutar: composer dump-autoload
require __DIR__ . '/vendor/autoload.php';

// Ahora todas las clases bajo App\ y todas las dependencias
// están disponibles sin ningún require adicional
use AppControladoresRegistroControlador;
use GuzzleHttpClient;
use CarbonCarbon;

$cliente  = new Client();
$hoy      = Carbon::now();
$registro = new RegistroControlador(/* ... */);
?>

Clases de mapa (classmap)

Para librerías que no siguen PSR-4, Composer puede escanear directorios y generar un mapa clase-fichero estático. Es más lento de generar pero puede ser más rápido en producción si se usa composer dump-autoload --optimize.

<?php
// composer.json con classmap para código heredado
// {
//   "autoload": {
//     "psr-4": { "App\": "src/" },
//     "classmap": ["legacy/", "lib/"],
//     "files": ["helpers/funciones_globales.php"]
//   }
// }

// "files" carga siempre esos ficheros al incluir vendor/autoload.php,
// ideal para funciones globales de ayuda
?>

La documentación oficial de spl_autoload_register() detalla el comportamiento de la pila de autoloaders, la función spl_autoload_unregister() para eliminar autoloaders y cómo combinar múltiples autoloaders registrados para distintos namespaces.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP