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.
