Estándar de carga automática PSR-4
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy. Lección 12 de 91.
PSR-4 es un estándar que define cómo deben cargarse automáticamente las clases de PHP según su espacio de nombres y la ubicación de sus archivos. En lugar de incluir manualmente cada archivo de clase, PSR-4 permite que PHP encuentre y cargue las clases automáticamente cuando las usas.
La regla principal es sencilla: el espacio de nombres debe coincidir con la estructura de directorios. Si tienes una clase App\Models\User, el archivo debe estar ubicado en App/Models/User.php.
<?php
// Archivo: src/Models/User.php
namespace App\Models;
class User {
public $name;
public function __construct($name) {
$this->name = $name;
}
}
Puedes escribir una función de autoloading sencilla que siga las reglas de PSR-4:
<?php
// Archivo: autoload.php
spl_autoload_register(function ($class) {
$prefix = 'App\\';
$baseDir = __DIR__ . '/src/';
// Comprueba si la clase usa nuestro prefijo de namespace
if (strpos($class, $prefix) === 0) {
$relativeClass = substr($class, strlen($prefix));
$file = $baseDir . str_replace('\\', '/', $relativeClass) . '.php';
if (file_exists($file)) {
require $file;
}
}
});
La función spl_autoload_register indica a PHP que llame a tu función cada vez que encuentre una clase desconocida. La función convierte el espacio de nombres en una ruta de archivo y la carga.
Punto clave: PSR-4 crea una correspondencia predecible entre los espacios de nombres y las rutas de archivo. Cuando ves App\Models\User, sabes de inmediato que el archivo está en src/Models/User.php. Esta convención facilita la navegación y el mantenimiento de los proyectos.
Desafío
FácilConstruyamos un sistema sencillo de carga automática PSR-4 que cargue automáticamente las clases según su espacio de nombres y la ubicación de sus archivos.
Crearás un proyecto con tres archivos que demuestran cómo PSR-4 asigna los espacios de nombres a las rutas de directorios:
src/Services/Logger.php: Define una claseLoggeren el espacio de nombresApp\Services. Debe tener una propiedadpublic $name, un constructor que acepte y establezca el nombre, y un métodolog($message)que devuelva"[name] logged: [message]".src/Services/Mailer.php: Define una claseMaileren el espacio de nombresApp\Services. Debe tener una propiedadpublic $sender, un constructor que acepte y establezca el remitente, y un métodosend($to)que devuelva"Mail from [sender] to [to]".main.php: Crea un cargador automático PSR-4 usandospl_autoload_registerque asigne el prefijo del espacio de nombresApp\al directoriosrc/. El cargador automático debe convertir los separadores de espacios de nombres en separadores de directorios y añadir.phppara encontrar el archivo correcto. Después de registrar el cargador automático, usa la palabra claveusepara importar ambas clases y, después, crea unLoggercon el nombre"FileLogger"y unMailercon el remitente"admin@site.com". Imprime el resultado de llamar alog("System started")en el registrador y asend("user@example.com")en el mailer (cada uno en su propia línea).
La idea clave es que tu función de carga automática recibe el nombre de clase completamente cualificado (como App\Services\Logger) y debe convertirlo en una ruta de archivo (src/Services/Logger.php). Usa strpos para comprobar si la clase comienza con el prefijo de tu espacio de nombres, substr para obtener el nombre de clase relativo y str_replace para convertir las barras invertidas en barras diagonales.
Pruébalo tú mismo
<?php
// Implementación de Autoloader PSR-4
// TODO: Registra un autoloader usando spl_autoload_register
// El autoloader debería:
// 1. Comprobar si la clase comienza con el prefijo de namespace 'App\'
// 2. Eliminar el prefijo 'App\' para obtener el nombre de clase relativo
// 3. Convertir los separadores de namespace (\) a separadores de directorio (/)
// 4. Anteponer 'src/' y añadir '.php' para construir la ruta del archivo
// 5. Requerir el archivo si existe
spl_autoload_register(function ($class) {
// TODO: Define el prefijo de namespace y el directorio base
// TODO: Comprueba si la clase usa el prefijo de namespace (usa strpos)
// TODO: Obtén el nombre de clase relativo (usa substr)
// TODO: Construye la ruta del archivo reemplazando \ con / (usa str_replace)
// TODO: Requiere el archivo si existe
});
// TODO: Usa la palabra clave 'use' para importar las clases Logger y Mailer
// TODO: Crea una instancia de Logger con el nombre "FileLogger"
// TODO: Crea una instancia de Mailer con el remitente "admin@site.com"
// TODO: Imprime el resultado de log("System started")
// TODO: Imprime el resultado de send("user@example.com")
?>Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de la POO
Archivos externosIntroducción a la POOClases frente a objetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Repaso: calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasRepaso - Jerarquía de empleados7Encapsulación
Público, protegido, privadoModificadores de acceso en profundidadGetters y settersOcultación de la informaciónPromoción del constructor (8.0)Repaso: sistema de registros de estudiantes10Conceptos avanzados de OOP
Composición vs. herenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibras (PHP 8.1)Análisis profundo de la clonación de objetosGeneradores e iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Namespaces y carga automática
Introducción a los NamespacesLa palabra clave useEstándar de carga automática PSR-4Autoloader de ComposerRepaso: proyecto organizado5Interfaces y contratos
Introducción a las interfacesImplementación de interfacesImplementación de múltiples interfacesInterfaces vs. clase abstractaTipado con interfacesRepaso - Calculadora de formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeRepaso: colección personalizada3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Repaso: gestor de cuentas bancarias6Polimorfismo
Repaso de la sobrescritura de métodosPolimorfismo mediante interfacesAnotaciones de tipo y tipos uniónEnlace estático tardíoRepaso: procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos entre TraitsMétodos abstractos en TraitsTraits frente a la herencia12Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón StrategyPractica por tu cuenta: Compilador de PHP online