Tema
Composer y autoload PSR-4
Composer es el gestor de dependencias de PHP: instala librerías (para enviar correos, generar PDFs, leer Excel...) con un comando y carga tus clases automáticamente. Ningún proyecto PHP profesional moderno se hace sin él, y Laravel depende completamente de Composer.
Concepto
Imagina que necesitas enviar correos, crear PDFs y manejar fechas. Sin Composer tendrías que descargar cada librería a mano, descomprimirla, incluir sus archivos en el orden correcto y actualizarla cuando salga una versión nueva. Composer hace todo eso por ti:
- Gestor de dependencias: lees en
composer.jsonqué librerías usa tu proyecto y Composer las descarga en la carpetavendor/. - Autoloader: genera un archivo
vendor/autoload.phpque carga cualquier clase justo cuando la usas. Adiós a las listas interminables derequire.
Las librerías se publican en Packagist, el "npm" o "tienda de apps" de PHP.
Instalación
Windows
- Descarga el instalador desde getcomposer.org (
Composer-Setup.exe). - Durante la instalación te pedirá la ruta de
php.exe(por ejemploC:\xampp\php\php.exeo la de Laragon). Laragon ya trae Composer incluido. - Abre una terminal nueva y comprueba:
powershell
composer --version
# Composer version 2.8.xLinux / macOS
bash
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"
sudo mv composer.phar /usr/local/bin/composer
composer --versionTu primer proyecto con Composer
bash
mkdir mi-proyecto
cd mi-proyecto
composer initcomposer init hace unas preguntas (nombre del paquete, descripción, autor...). Puedes aceptar los valores por defecto. Al final se crea un composer.json.
Instalar una librería
Vamos a instalar nesbot/carbon, la librería de fechas que usa Laravel:
bash
composer require nesbot/carbonEsto:
- Añade la librería a
composer.json. - La descarga (junto con sus propias dependencias) en
vendor/. - Crea
composer.lockcon las versiones exactas instaladas. - Regenera
vendor/autoload.php.
Úsala:
php
<?php
// index.php
declare(strict_types=1);
// Una sola línea carga TODAS las librerías instaladas
require __DIR__ . '/vendor/autoload.php';
use Carbon\Carbon;
Carbon::setLocale('es');
$fecha = Carbon::parse('2026-10-18 10:00');
echo $fecha->diffForHumans() . PHP_EOL; // hace 4 horas
echo $fecha->addDays(10)->translatedFormat('l j \d\e F'), PHP_EOL; // miércoles 28 de octubreAnatomía de composer.json
json
{
"name": "erick/mi-proyecto",
"description": "Sistema de reservas para un consultorio",
"type": "project",
"require": {
"php": ">=8.3",
"nesbot/carbon": "^3.8",
"phpmailer/phpmailer": "^6.9",
"vlucas/phpdotenv": "^5.6"
},
"require-dev": {
"phpunit/phpunit": "^11.0"
},
"autoload": {
"psr-4": {
"App\\": "src/"
},
"files": [
"src/helpers.php"
]
},
"scripts": {
"test": "phpunit tests",
"serve": "php -S localhost:8000 -t public"
}
}- require: lo que necesita el proyecto para funcionar en producción.
- require-dev: herramientas sólo para desarrollo (tests, depuración). Se instalan con
composer require --dev paquete. - autoload: cómo cargar tus clases (lo vemos ahora).
- scripts: atajos.
composer serveejecuta el servidor integrado.
Versiones: qué significa ^ y ~
Las versiones siguen el formato MAYOR.MENOR.PARCHE (versionado semántico):
| Restricción | Acepta | Ejemplo |
|---|---|---|
^3.8 | Desde 3.8.0 hasta antes de 4.0.0 | 3.8.1, 3.9, 3.15 |
~3.8 | Desde 3.8.0 hasta antes de 3.9.0 | 3.8.1, 3.8.7 |
3.8.2 | Exactamente esa | 3.8.2 |
>=8.3 | Esa o mayor | 8.3, 8.4 |
^ es la opción recomendada: recibes correcciones y mejoras sin cambios que rompan tu código (que sólo llegan en versiones mayores).
Autoload PSR-4
PSR-4 es un estándar que dice: "el namespace de una clase corresponde a su ruta de carpetas". Con la regla "App\\": "src/":
| Clase | Archivo |
|---|---|
App\Usuario | src/Usuario.php |
App\Modelos\Producto | src/Modelos/Producto.php |
App\Http\Controladores\InicioControlador | src/Http/Controladores/InicioControlador.php |
Reglas:
- Un archivo = una clase.
- El nombre del archivo es exactamente el nombre de la clase (con mayúsculas) +
.php. - El namespace sigue la estructura de carpetas.
Ejemplo completo
Estructura:
txt
mi-proyecto/
├── composer.json
├── public/
│ └── index.php
├── src/
│ ├── helpers.php
│ ├── Modelos/
│ │ └── Producto.php
│ └── Servicios/
│ └── Calculadora.php
└── vendor/ ← lo crea Composerphp
<?php
// src/Modelos/Producto.php
declare(strict_types=1);
namespace App\Modelos;
final class Producto
{
public function __construct(
public readonly string $nombre,
public readonly float $precio,
) {}
}php
<?php
// src/Servicios/Calculadora.php
declare(strict_types=1);
namespace App\Servicios;
use App\Modelos\Producto;
final class Calculadora
{
public function __construct(private float $iva = 0.16) {}
/** @param Producto[] $productos */
public function total(array $productos): float
{
$subtotal = array_sum(array_map(fn (Producto $p) => $p->precio, $productos));
return round($subtotal * (1 + $this->iva), 2);
}
}php
<?php
// src/helpers.php — funciones globales cargadas con "files"
declare(strict_types=1);
function dinero(float $cantidad): string
{
return '$' . number_format($cantidad, 2);
}
function e(?string $texto): string
{
return htmlspecialchars($texto ?? '', ENT_QUOTES, 'UTF-8');
}php
<?php
// public/index.php
declare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use App\Modelos\Producto;
use App\Servicios\Calculadora;
$productos = [
new Producto('Teclado', 650),
new Producto('Mouse', 350),
];
$calc = new Calculadora();
echo 'Total con IVA: ' . dinero($calc->total($productos)); // Total con IVA: $1,160.00Cada vez que cambies la sección autoload de composer.json, regenera el autoloader:
bash
composer dump-autoloadCon PSR-4 no necesitas ejecutarlo al crear clases nuevas: Composer las encuentra solas siguiendo la regla. Sólo al modificar composer.json.
Error común
Class "App\Modelos\Producto" not found. Revisa, en este orden:
- ¿Incluiste
vendor/autoload.php? - ¿El namespace del archivo coincide con la carpeta?
- ¿El nombre del archivo coincide exactamente con la clase? En Windows
producto.phpfunciona por casualidad, pero en el servidor Linux falla porque distingue mayúsculas. - ¿Ejecutaste
composer dump-autoloaddespués de editarcomposer.json?
Comandos esenciales
bash
composer install # instala lo que dice composer.lock (úsalo al clonar un proyecto)
composer require vendor/pkg # añade una dependencia
composer require --dev vendor/pkg # dependencia sólo de desarrollo
composer remove vendor/pkg # quita una dependencia
composer update # actualiza dentro de las restricciones y reescribe composer.lock
composer update vendor/pkg # actualiza sólo un paquete
composer outdated # muestra qué paquetes tienen versiones nuevas
composer audit # revisa vulnerabilidades conocidas en tus dependencias
composer dump-autoload -o # autoloader optimizado (para producción)
composer install --no-dev --optimize-autoloader # instalación de produccióninstall vs update
composer installrespeta exactamente las versiones decomposer.lock. Todo el equipo y el servidor tendrán las mismas versiones.composer updatebusca versiones nuevas y modificacomposer.lock. Hazlo a propósito, en desarrollo, y prueba antes de subir.
Buena práctica
- Sube a Git
composer.jsonycomposer.lock. - No subas
vendor/(agrégalo a.gitignore). Se regenera concomposer install. - Ejecuta
composer auditantes de cada entrega a un cliente.
Variables de entorno con phpdotenv
Un paquete que usarás en todos tus proyectos: separa las credenciales del código.
bash
composer require vlucas/phpdotenvenv
# .env (NO se sube a Git)
APP_ENV=local
DB_HOST=127.0.0.1
DB_NAME=tienda
DB_USER=root
DB_PASS=php
<?php
// config/bootstrap.php
require __DIR__ . '/../vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/..');
$dotenv->load();
// Obliga a que existan estas variables (lanza excepción si falta alguna)
$dotenv->required(['DB_HOST', 'DB_NAME', 'DB_USER']);
$dbHost = $_ENV['DB_HOST'];Más sobre esto en Gestión de secretos.
Subir a hosting compartido sin terminal
Muchos hostings compartidos no tienen SSH. Solución:
- En tu computadora ejecuta
composer install --no-dev --optimize-autoloader. - Sube todo, incluida la carpeta
vendor/, por FTP o el administrador de archivos de cPanel. - Asegúrate de que la versión de PHP del hosting sea igual o mayor a la que pide
composer.json.
Ejercicios
- Crea un proyecto con Composer, configura PSR-4 con el namespace
Tienda\apuntando asrc/, y crea las clasesTienda\Catalogo\ProductoyTienda\Catalogo\Categoria. Úsalas desdepublic/index.php. - Instala
ramsey/uuidy genera 3 identificadores únicos. - Agrega un script
"serve"encomposer.jsonque levante el servidor enpublic/y ejecútalo concomposer serve.
Ver solución
json
{
"name": "erick/tienda",
"require": {
"php": ">=8.3",
"ramsey/uuid": "^4.7"
},
"autoload": {
"psr-4": { "Tienda\\": "src/" }
},
"scripts": {
"serve": [
"Composer\\Config::disableProcessTimeout",
"php -S localhost:8000 -t public"
]
}
}php
<?php
// src/Catalogo/Categoria.php
declare(strict_types=1);
namespace Tienda\Catalogo;
final class Categoria
{
public function __construct(public readonly string $nombre) {}
}php
<?php
// src/Catalogo/Producto.php
declare(strict_types=1);
namespace Tienda\Catalogo;
final class Producto
{
public function __construct(
public readonly string $nombre,
public readonly Categoria $categoria,
) {}
}php
<?php
// public/index.php
declare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use Ramsey\Uuid\Uuid;
use Tienda\Catalogo\{Categoria, Producto}; // importación agrupada
$cat = new Categoria('Café');
$p = new Producto('Café de Veracruz', $cat);
echo "{$p->nombre} ({$p->categoria->nombre})<br>";
for ($i = 0; $i < 3; $i++) {
echo Uuid::uuid4()->toString() . '<br>';
}bash
composer dump-autoload
composer serveResumen
- Composer instala librerías de Packagist en
vendor/y generavendor/autoload.php. composer.jsondeclara dependencias;composer.lockfija las versiones exactas.- PSR-4: el namespace corresponde a la carpeta y el nombre del archivo a la clase.
composer installpara instalar lo existente,composer requirepara añadir,composer updatesólo a propósito.- No subas
vendor/a Git; sícomposer.jsonycomposer.lock. - En producción:
composer install --no-dev --optimize-autoloaderycomposer audit.