🎭 Composer: El Invocador de Dependencias en PHP

“Un ninja de PHP sin Composer es como un samurái sin katana: limitado y obsoleto.” - Código del Desarrollo Moderno

🎯 ¿Qué es Composer?

Composer es el gestor de paquetes estándar para PHP, equivalente a npm en JavaScript.

Características:

  • Gestiona dependencias de proyectos PHP
  • Resuelve versiones compatibles automáticamente
  • Sistema de autoload inteligente (no más require manuales)
  • Usado por frameworks modernos: Laravel, Symfony, WordPress moderno

Instalación:

macOS/Linux:

# Descarga el instalador
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"

# Verifica integridad (hash cambia, revisa getcomposer.org)
php composer-setup.php

# Mueve a PATH global
sudo mv composer.phar /usr/local/bin/composer

# Verifica instalación
composer --version
# Composer version 2.7.0

Windows:

Descarga el instalador gráfico: Composer for Windows


📜 El Corazón: composer.json

Similar a package.json en npm, composer.json define:

  • Nombre y descripción del proyecto
  • Dependencias de producción (require)
  • Dependencias de desarrollo (require-dev)
  • Configuración de autoload
  • Scripts personalizados

Crear un composer.json

Método interactivo:

composer init
# Te preguntará: nombre del paquete, descripción, autor, etc.

Método manual:

{
    "name": "ninja/mi-proyecto",
    "description": "Aplicación ninja en PHP",
    "type": "project",
    "require": {
        "php": "^8.1"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

📦 Instalar Paquetes

Sintaxis Básica

# Instalar dependencia de producción
composer require guzzlehttp/guzzle

# Instalar dependencia de desarrollo
composer require --dev phpunit/phpunit

# Atajos
composer req guzzlehttp/guzzle         # require
composer req --dev phpunit/phpunit     # require-dev

Qué sucede:

  1. Composer descarga el paquete desde packagist.org
  2. Lo guarda en vendor/guzzlehttp/guzzle/
  3. Actualiza composer.json:
    "require": {
        "guzzlehttp/guzzle": "^7.8"
    }
  4. Crea/actualiza composer.lock (versiones exactas)
  5. Actualiza vendor/autoload.php

🔍 require vs require-dev

require (Producción)

Dependencias que tu aplicación necesita para funcionar en producción.

composer require guzzlehttp/guzzle
composer require monolog/monolog
composer require vlucas/phpdotenv

Ejemplos:

  • Cliente HTTP (Guzzle)
  • Logger (Monolog)
  • Variables de entorno (phpdotenv)
  • ORM (Doctrine, Eloquent)

require-dev (Desarrollo)

Herramientas que solo necesitas en desarrollo/testing.

composer require --dev phpunit/phpunit
composer require --dev squizlabs/php_codesniffer
composer require --dev phpstan/phpstan

Ejemplos:

  • Framework de testing (PHPUnit)
  • Linters (PHP_CodeSniffer)
  • Analizadores estáticos (PHPStan, Psalm)
  • Debuggers (Xdebug)

Diferencia en despliegue:

# En servidor de producción, instala solo 'require'
composer install --no-dev

# Esto ignora phpunit, phpstan, etc.

🎯 Autoload: El Jutsu Más Poderoso

El autoload de Composer elimina la necesidad de escribir require manual para cada clase.

Antes de Composer (el infierno):

<?php
require_once 'src/Database/Connection.php';
require_once 'src/Models/User.php';
require_once 'src/Controllers/UserController.php';
require_once 'vendor/guzzle/src/Client.php';
require_once 'vendor/guzzle/src/Exception/RequestException.php';
// ... 50 requires más

Con Composer (el paraíso):

<?php
require_once 'vendor/autoload.php';

use App\Controllers\UserController;
use GuzzleHttp\Client;

$controller = new UserController();
$http = new Client();

Composer carga automáticamente las clases cuando las usas.

Configurar Autoload en composer.json

PSR-4 (recomendado):

{
    "autoload": {
        "psr-4": {
            "App\\": "src/",
            "Database\\": "database/"
        }
    }
}

Significado:

  • Clases en src/Models/User.php → namespace App\Models
  • Clases en database/migrations/CreateUsersTable.php → namespace Database\migrations

Ejemplo de uso:

// Archivo: src/Models/User.php
<?php
namespace App\Models;

class User {
    public function getName() {
        return "Ninja";
    }
}
// Archivo: index.php
<?php
require 'vendor/autoload.php';

use App\Models\User;

$user = new User();
echo $user->getName(); // Ninja

Actualizar autoload después de cambios:

composer dump-autoload

Autoload de Archivos Individuales

Para archivos que no son clases (helpers, constantes):

{
    "autoload": {
        "files": [
            "src/helpers.php",
            "config/constants.php"
        ]
    }
}

Estos archivos se cargan automáticamente con vendor/autoload.php.


📂 Estructura de Directorios

mi-proyecto-php/
├── vendor/              # NUNCA versionar en Git
│   ├── autoload.php     # Archivo mágico de autoload
│   ├── composer/        # Metadatos de Composer
│   └── guzzlehttp/      # Dependencias instaladas
├── src/
│   ├── Models/
│   │   └── User.php
│   └── Controllers/
│       └── UserController.php
├── public/
│   └── index.php
├── .gitignore           # Debe incluir /vendor/
├── composer.json
└── composer.lock

⚠️ CRÍTICO: .gitignore

/vendor/
composer.phar

Por qué:

  • vendor/ puede pesar cientos de MB
  • Es reproducible con composer install

⚡ Comandos Esenciales de Composer

Instalar Dependencias

# Instalar desde composer.json (proyecto existente)
composer install

# Instalar respetando composer.lock (producción)
composer install --no-dev --optimize-autoloader

Actualizar Paquetes

# Ver paquetes desactualizados
composer outdated

# Actualizar TODOS los paquetes (respetando restricciones)
composer update

# Actualizar un paquete específico
composer update guzzlehttp/guzzle

# Actualizar a última versión (ignorar restricciones)
composer require guzzlehttp/guzzle:^8.0

Eliminar Paquetes

# Desinstalar paquete
composer remove guzzlehttp/guzzle

# Atajo
composer rem guzzlehttp/guzzle

Buscar Paquetes

# Buscar en packagist.org
composer search monolog

# Ver info de un paquete
composer show guzzlehttp/guzzle

Validar composer.json

# Verificar sintaxis
composer validate

Autoload

# Regenerar autoload (después de añadir clases)
composer dump-autoload

# Optimizar para producción (más rápido)
composer dump-autoload --optimize

🎯 Flujo de Trabajo Real

Proyecto Nuevo

# 1. Crear directorio
mkdir mi-app-php
cd mi-app-php

# 2. Inicializar Composer
composer init

# 3. Instalar dependencias
composer require vlucas/phpdotenv
composer require --dev phpunit/phpunit

# 4. Configurar autoload en composer.json
{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

# 5. Regenerar autoload
composer dump-autoload

# 6. Crear .gitignore
echo "/vendor/" > .gitignore

# 7. Inicializar Git
git init
git add .
git commit -m "feat: inicializar proyecto PHP"

Clonar Proyecto Existente

# 1. Clonar repositorio
git clone https://github.com/usuario/proyecto-php.git
cd proyecto-php

# 2. Instalar dependencias
composer install

# 3. Configurar .env (si usa phpdotenv)
cp .env.example .env

# 4. Ejecutar servidor
php -S localhost:8000 -t public

💡 Paquetes Esenciales para PHP

Cliente HTTP

composer require guzzlehttp/guzzle
use GuzzleHttp\Client;

$client = new Client();
$response = $client->get('https://api.github.com/users/octocat');
echo $response->getBody();

Logger

composer require monolog/monolog
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('app');
$log->pushHandler(new StreamHandler('app.log', Logger::WARNING));
$log->warning('Advertencia ninja');

Variables de Entorno

composer require vlucas/phpdotenv
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

$dbHost = $_ENV['DB_HOST'];

Testing

composer require --dev phpunit/phpunit
vendor/bin/phpunit tests/

Validación

composer require respect/validation
use Respect\Validation\Validator as v;

$email = v::email()->validate('ninja@8devmx.com'); // true

🎯 Reto Ninja del Tema

Misión: Crear proyecto PHP con Composer

  1. Inicializa proyecto:

    mkdir composer-dojo
    cd composer-dojo
    composer init -n
  2. Instala Guzzle:

    composer require guzzlehttp/guzzle
  3. Configura autoload en composer.json:

    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
  4. Crea clase src/HttpClient.php:

    <?php
    namespace App;
    
    use GuzzleHttp\Client;
    
    class HttpClient {
        public function fetchUser($username) {
            $client = new Client();
            $response = $client->get("https://api.github.com/users/$username");
            return json_decode($response->getBody(), true);
        }
    }
  5. Crea index.php:

    <?php
    require 'vendor/autoload.php';
    
    use App\HttpClient;
    
    $http = new HttpClient();
    $user = $http->fetchUser('torvalds');
    echo "Nombre: " . $user['name'] . "\n";
  6. Ejecuta:

    composer dump-autoload
    php index.php

Criterios de éxito:

  • ✅ Guzzle funciona sin require manual
  • ✅ Autoload PSR-4 carga tu clase
  • vendor/ está en .gitignore
  • ✅ Obtuviste datos de la API de GitHub

⚠️ Errores Comunes

Error #1: Class not found

Fatal error: Class 'App\Models\User' not found

Causa: Olvidaste ejecutar composer dump-autoload

Solución:

composer dump-autoload

Error #2: require vs require-dev confundido

# Instalaste PHPUnit en producción por error
composer require phpunit/phpunit  # ❌

# Debió ser:
composer require --dev phpunit/phpunit  # ✅

Error #3: Versiones en conflicto

Your requirements could not be resolved to an installable set of packages.

Causa: Dos paquetes requieren versiones incompatibles de una dependencia común.

Solución:

# Ver conflictos
composer why-not php 8.2

# Actualizar paquetes
composer update

📚 Recursos Adicionales


Siguiente Pergamino: 4.5 pnpm: El Ninja de la Eficiencia

¿Creaste tu primer proyecto con Composer? Comparte tu código en Discord con #ComposerNinja! 🎭🥷