Composer es un gestor de dependencias para PHP. Eso significa que se encarga de descargar las librerías que necesita tu proyecto, mantenerlas en la versión correcta y generar el autoloader para que puedas usarlas sin tener que hacer require a mano en cada archivo.
Antes de que apareciera en 2012, las opciones eran copiar archivos PHP de una librería a otra a mano o usar PEAR, que era la herramienta oficial pero funcionaba bastante mal. Hoy cualquier proyecto PHP mínimamente serio usa Composer. Packagist, el repositorio central de paquetes, tiene más de 300.000 paquetes disponibles, desde frameworks enteros como Laravel o Symfony hasta utilidades pequeñas para trabajar con fechas, tokens JWT o PDFs.
Si arrancas un proyecto PHP en 2026 sin Composer, vas a tener que justificarlo.
composer.json y composer.lock: para qué sirve cada uno
Estos dos archivos son los que más confusión generan al principio, pero la distinción es sencilla:
- composer.json: lo defines tú. Aquí dices qué paquetes necesita tu proyecto y con qué restricciones de versión.
- composer.lock: lo genera Composer. Contiene las versiones exactas de todos los paquetes instalados, incluyendo las dependencias de tus dependencias.
El archivo composer.lock debe ir siempre en el repositorio de git. Si no lo subes, cuando alguien ejecute composer install en producción puede que instale versiones distintas a las que tienes en local, y eso es una fuente de bugs bastante desagradables.
La diferencia entre composer install y composer update también conviene tenerla clara:
composer install: instala exactamente lo que dice el lockfile. Es lo que debes usar en producción y en CI.composer update: resuelve las dependencias de nuevo según las restricciones delcomposer.json, actualiza los paquetes a las versiones más recientes posibles y regenera el lockfile. Úsalo solo cuando quieras actualizar paquetes de forma intencionada.
Restricciones de versión: qué significa cada símbolo
Cuando añades una dependencia en composer.json, especificas una restricción de versión. Las más habituales son:
"require": {
"monolog/monolog": "^2.0",
"guzzlehttp/guzzle": "~7.4",
"vendor/legacy-lib": "1.3.2"
}
"^2.0": cualquier versión >=2.0.0 y <3.0.0. Respeta semver y es la restricción más usada."~2.1": cualquier versión >=2.1.0 y <2.2.0. Más restrictivo que el caret."*": cualquier versión. Nunca lo uses en producción."1.3.2": exactamente esa versión. Muy restrictivo y raramente necesario cuando ya tienes lockfile."dev-main": la rama main del repositorio. Solo para desarrollo local o cuando necesitas algo que aún no tiene release.
El caret (^) funciona bien para la mayoría de los casos porque respeta semver: si el autor del paquete sigue correctamente el versionado semántico, una versión minor nunca debería romperte el código.
Autoloading: cómo Composer carga las clases
Una de las cosas más útiles de Composer es que genera el autoloader automáticamente. En vez de hacer require_once a cada clase, añades una sola línea al principio de tu aplicación:
<?php
require_once __DIR__ . '/vendor/autoload.php';
Y a partir de ahí, todas las clases de tus dependencias y las tuyas propias están disponibles. Para que Composer sepa dónde están tus clases, tienes que decírselo en composer.json:
"autoload": {
"psr-4": {
"App\": "src/"
}
}
Esto significa que las clases bajo el namespace App se buscan en la carpeta src/. Por ejemplo, AppControllersUserController corresponde al archivo src/Controllers/UserController.php.
PSR-4 es el estándar que usa prácticamente todo el mundo. Si tienes código legacy sin namespaces, puedes usar classmap en su lugar, que escanea directorios y mapea clases directamente.
Cada vez que añades carpetas nuevas o cambias la estructura, ejecuta:
composer dump-autoload
Esto regenera el mapa de clases. En producción conviene añadir --optimize para que genere un classmap estático en vez de usar reglas PSR-4 dinámicas, lo que acelera la carga de clases.
Scripts de Composer
Composer permite definir scripts que puedes ejecutar con composer run. No tienen por qué ser solo PHP:
"scripts": {
"test": "phpunit --testdox",
"lint": "php-cs-fixer fix src/ --dry-run",
"analyse": "phpstan analyse src/ --level=8"
}
Para ejecutar uno:
composer run test
También puedes definir hooks que se ejecutan automáticamente en determinados momentos. Los más usados son post-install-cmd y post-update-cmd, que se disparan justo después de instalar o actualizar dependencias:
"scripts": {
"post-install-cmd": [
"php artisan migrate --force",
"php artisan config:cache"
]
}
Si necesitas ejecutar un hook manualmente:
composer run-script post-install-cmd
Paquetes privados y repositorios alternativos
No todos los paquetes están en Packagist. Si tienes librerías internas o de pago, puedes añadir repositorios alternativos en composer.json:
"repositories": [
{
"type": "vcs",
"url": "[email protected]:miempresa/mi-paquete"
}
]
Con esto, Composer busca en ese repositorio de Git además de en Packagist. Funciona bien para paquetes privados en GitHub, GitLab o Bitbucket.
Si tienes varios paquetes internos, montar Satis puede tener sentido. Es un Packagist privado que puedes alojar tú mismo, de código abierto y mantenido por los mismos autores de Composer. La alternativa gestionada es Private Packagist, de pago pero sin infraestructura que mantener.
Composer 2.x: qué cambió desde 2020
Composer 2 se lanzó en 2020 y fue un cambio importante en rendimiento. La resolución de dependencias pasó a ser paralela, lo que reduce considerablemente el tiempo de instalación en proyectos grandes. Si tienes algún servidor de CI que sigue con Composer 1, es el momento de actualizarlo.
Composer 2 también mejoró el sistema de plugins con sandboxing de permisos. Los plugins ahora declaran qué operaciones necesitan hacer, lo que reduce el riesgo de que un plugin malicioso haga cosas que no debería.
Dos comandos que conviene conocer si no los usas ya:
# Comprueba si alguna dependencia tiene vulnerabilidades conocidas
composer audit
# Muestra qué paquetes tienen versiones más nuevas disponibles
composer outdated
composer audit consulta la base de datos de advisories de seguridad de Packagist. Es rápido y puede ahorrarte un susto. Tiene sentido ejecutarlo en CI junto con los tests.
Buenas prácticas en 2026
Algunas cosas que marcan la diferencia en el día a día:
En producción, siempre con estas opciones
composer install --no-dev --optimize-autoloader
--no-dev excluye las dependencias de desarrollo (PHPUnit, PHPStan, etc.) y --optimize-autoloader genera un classmap estático en vez de usar autoloading dinámico. Los dos juntos reducen el peso de vendor/ y aceleran un poco la aplicación.
Separa las dependencias de desarrollo
composer require --dev phpunit/phpunit
composer require --dev phpstan/phpstan
Todo lo que solo necesitas para desarrollar o testear va con --dev. Así no acabas instalando PHPUnit en producción.
Actualiza con cuidado
En vez de ejecutar composer update a secas (que actualiza todo), actualiza paquete a paquete:
composer update vendor/paquete
Esto limita el alcance del cambio y hace más fácil detectar qué actualización introdujo un problema si algo falla.
Comandos útiles para el día a día
# Por qué está instalado este paquete
composer why vendor/paquete
# Qué dependencias bloquean la actualización a PHP 8.4
composer prohibits php 8.4
# Ver todas las dependencias en forma de árbol
composer depends vendor/paquete
composer why es especialmente útil cuando encuentras un paquete en vendor/ que no recuerdas haber instalado directamente. Te dice qué dependencia lo requirió.
No cometas vendor/
La carpeta vendor/ no va en git. Añádela al .gitignore. Lo que sí va en git es composer.lock, que es suficiente para reproducir exactamente el mismo estado en cualquier máquina.
Si tienes un entorno sin acceso a internet en producción, la opción es usar composer install --no-interaction antes del despliegue o crear un paquete vendor.tar.gz en CI y desplegarlo junto con el código.
Recursos para seguir
La documentación oficial de Composer en getcomposer.org está bastante bien mantenida y cubre todos los casos de uso que puedas necesitar. Para Composer en el flujo TDD: gestión de dependencias para testing y para saber más sobre seguridad en paquetes PHP: composer audit y vulnerabilidades, tienes más contexto en estos artículos.
Imagen: Pexels / Daniil Komov
