---
name: build-errors-php
description: >
  Resolución de errores de build e instalación PHP: Composer, autoload, errores de
  PHP fatal/parse, incompatibilidades de versión, extensiones faltantes y errores
  de Laravel/Artisan. Cargar cuando un build PHP falle, Composer reporte conflictos,
  o haya errores de autoload o extensiones faltantes.
version: "1.0.0"
herramientasPermitidas: [Read, Bash, Grep]
exclusiones:
  - "No cargar para errores lógicos de la aplicación PHP en runtime (QueryException, ErrorException por lógica incorrecta) cuando Composer y autoload funcionan — si la app arranca pero falla en una ruta específica, es un bug de lógica, no de build."
  - "No cargar para fallos de PHPUnit/Pest en assertions cuando el autoload funciona correctamente — si `vendor/autoload.php` carga bien pero los tests fallan por valores incorrectos, es un error de lógica de tests."
  - "No cargar para diseñar la arquitectura Laravel desde cero (Service Providers, Eloquent models, repositorios) — si la pregunta es cómo estructurar un proyecto nuevo, cargar `php-patrones` o `php-experto`."
  - "No cargar para errores de configuración de servidor web (Nginx, Apache, PHP-FPM) que no son errores de Composer o autoload — si la app falla a nivel de servidor, es configuración de infraestructura."
evolvable: true  # default para skill estandar
---
# Build Errors PHP — Diagnóstico y Solución

## Cuándo NO cargar

- Composer y autoload funcionan pero la app falla en una ruta específica — es un bug de lógica de la aplicación, no de build.
- PHPUnit compila y carga pero los tests fallan en assertions — es un error de lógica de tests.
- La pregunta es cómo diseñar la arquitectura Laravel — para diseño cargar `php-patrones`.

## Cuándo cargar

- `composer install` o `composer update` falla con conflictos de dependencias
- Errores fatales de PHP (`Class not found`, `Call to undefined function`)
- Errores de autoload (`Class ... not found` después de agregar clases nuevas)
- `php artisan` falla con errores de configuración o migraciones
- Extensiones PHP faltantes (`ext-mbstring`, `ext-pdo`, `ext-gd`)
- Incompatibilidades de versión de PHP (7.4 vs 8.1 vs 8.3)
- Errores de `phpunit` o `pest` al ejecutar tests

---

## Errores de Composer — causa y solución

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

**Causa**: dos dependencias requieren versiones incompatibles de una tercera.

```bash
# Diagnóstico: ver el árbol de dependencias
composer why nombre-paquete
composer depends nombre-paquete

# Ver conflicto específico
composer why-not nombre-paquete version
```

**Soluciones**:
1. Actualizar la dependencia problemática: `composer update nombre-paquete --with-dependencies`
2. Relajar la restricción de versión en `composer.json`
3. Agregar alias de versión si la incompatibilidad es menor

### `Package ... requires php ^8.1 but your php version (7.4) does not satisfy`

**Causa**: el paquete requiere una versión de PHP más nueva.

```bash
# Verificar versión de PHP
php -v

# Verificar qué versión ve Composer
composer diagnose

# Forzar versión de plataforma (último recurso, puede ocultar problemas)
composer config platform.php 8.1
```

**Solución real**: actualizar PHP a la versión requerida.

### `Class ... not found` después de `composer install`

**Diagnóstico**:
```bash
# ¿El autoload está regenerado?
composer dump-autoload

# ¿El namespace coincide con la estructura de directorios?
# Verificar psr-4 en composer.json
grep -A5 '"psr-4"' composer.json
```

**Causa frecuente**: el namespace de la clase no coincide con la ruta del archivo.
Con PSR-4, `App\Services\FacturaService` debe estar en `app/Services/FacturaService.php`
(respetando mayúsculas exactas).

**Gotcha en Linux**: el filesystem es case-sensitive. `FacturaService.php` y
`facturaservice.php` son archivos distintos. En macOS/Windows funciona, en
producción (Linux) falla.

---

## Errores de extensiones PHP

### `Call to undefined function ...` o `Class ... not found` (extensión faltante)

**Extensiones comunes requeridas**:

| Extensión | Requerida por | Instalación Ubuntu |
|-----------|--------------|-------------------|
| `ext-mbstring` | Laravel, Symfony | `apt install php-mbstring` |
| `ext-xml` | PHPUnit, Composer | `apt install php-xml` |
| `ext-curl` | Guzzle, HTTP clients | `apt install php-curl` |
| `ext-gd` | Procesamiento de imágenes | `apt install php-gd` |
| `ext-pdo_mysql` | MySQL con PDO | `apt install php-mysql` |
| `ext-pdo_pgsql` | PostgreSQL con PDO | `apt install php-pgsql` |
| `ext-redis` | Cache/sesiones Redis | `pecl install redis` |
| `ext-zip` | Composer, manejo de ZIP | `apt install php-zip` |
| `ext-bcmath` | Cálculos de precisión | `apt install php-bcmath` |
| `ext-intl` | Internacionalización | `apt install php-intl` |

```bash
# Ver extensiones instaladas
php -m

# Verificar si una extensión específica está activa
php -m | grep -i mbstring

# Ver la configuración de PHP (php.ini activo)
php --ini
```

**Gotcha**: en sistemas con múltiples versiones de PHP, `php -m` puede mostrar
extensiones de una versión distinta a la que usa el servidor web. Verificar con
`phpinfo()` en el servidor.

---

## Errores de Laravel / Artisan

### `SQLSTATE[HY000] [2002] Connection refused`

**Causa**: la base de datos no está accesible con la configuración de `.env`.

```bash
# Verificar configuración
php artisan config:clear
php artisan config:show database

# Verificar conectividad
php artisan db:monitor
```

**Gotcha con Docker**: si la BD corre en Docker, el host no es `localhost` sino
el nombre del servicio (`mysql`, `postgres`) definido en `docker-compose.yml`.

### `The key ... was not found in the cipher`

**Causa**: falta la clave de aplicación.

```bash
php artisan key:generate
```

### `Class "App\Models\..." not found` en producción

**Causa común**: el cache de configuración/clases tiene datos viejos.

```bash
# Limpiar todos los caches
php artisan optimize:clear

# O individualmente:
php artisan config:clear
php artisan cache:clear
php artisan route:clear
php artisan view:clear
composer dump-autoload -o
```

### `Migration ... already exists` o errores de migraciones

```bash
# Ver estado de migraciones
php artisan migrate:status

# Correr migraciones pendientes
php artisan migrate

# Si la tabla migrations está corrupta (último recurso)
php artisan migrate:fresh --seed  # DESTRUCTIVO: borra todas las tablas
```

---

## Errores de PHP fatal / parse

### `Parse error: syntax error, unexpected ...`

**Causa**: sintaxis de versión nueva usada en PHP viejo.

| Sintaxis | Versión mínima |
|----------|---------------|
| `match` expression | PHP 8.0 |
| Named arguments `fn(name: $val)` | PHP 8.0 |
| Union types `int\|string` | PHP 8.0 |
| `enum` | PHP 8.1 |
| Fibers | PHP 8.1 |
| Readonly properties | PHP 8.1 |
| Intersection types `A&B` | PHP 8.1 |
| `readonly` classes | PHP 8.2 |
| DNF types `(A&B)\|null` | PHP 8.2 |
| `#[\Override]` attribute | PHP 8.3 |
| Typed class constants | PHP 8.3 |

```bash
# Verificar versión de PHP
php -v

# Verificar sintaxis sin ejecutar
php -l archivo.php
```

### `Allowed memory size of N bytes exhausted`

```bash
# Aumentar memoria temporalmente
php -d memory_limit=512M artisan migrate

# En php.ini
memory_limit = 256M

# En Composer (común con muchas dependencias)
COMPOSER_MEMORY_LIMIT=-1 composer update
```

---

## Errores de PHPUnit / Pest

### `Class "Tests\TestCase" not found`

```bash
# Regenerar autoload incluyendo dev
composer dump-autoload

# Verificar que phpunit.xml tiene el bootstrap correcto
grep bootstrap phpunit.xml
# Debe apuntar a vendor/autoload.php
```

### `No tests executed!`

**Causas comunes**:
1. Los archivos de test no siguen la convención de nombres (`*Test.php` para PHPUnit)
2. Los métodos de test no tienen prefijo `test_` ni anotación `@test`
3. El directorio de tests no está configurado en `phpunit.xml`

---

## Gotchas / Errores comunes no obvios

- **`Class "App\Models\Usuario" not found`** después de crear el modelo aunque el archivo existe con el nombre correcto: el autoload de Composer no se ha regenerado después de crear el archivo. Causa: Composer cachea el mapa de clases PSR-4; los archivos nuevos no se detectan hasta que se ejecuta `composer dump-autoload`. Solución: ejecutar `composer dump-autoload` después de crear cualquier clase PHP nueva — en desarrollo local es conveniente usar `composer dump-autoload -o` (optimizado) para detectar el problema antes de llegar a producción.
- **`composer install` falla con "platform check failed" en CI aunque la versión de PHP es la correcta**: el `platform` configurado en `composer.json` requiere extensiones PHP que están en el servidor de desarrollo pero no en la imagen de CI. Causa: la clave `config.platform.php` en composer.json fija la plataforma pero no las extensiones; si el lock fue generado con extensiones disponibles localmente, el CI puede carecer de ellas. Solución: verificar con `php -m` en CI qué extensiones están disponibles y agregar la imagen base correcta de PHP que incluya `ext-mbstring`, `ext-pdo`, etc., o instalarlas en el step de setup.
- **`php artisan migrate` falla con "SQLSTATE[HY000] [2002] Connection refused"** aunque las variables de entorno parecen correctas: el archivo `.env` en CI no tiene las credenciales de base de datos o el servicio de base de datos no está iniciado todavía en el pipeline. Causa: en pipelines de CI como GitHub Actions, el servicio de base de datos se inicia de forma asíncrona y puede no estar listo cuando `php artisan migrate` corre. Solución: agregar un health check que espere a que la base de datos esté disponible antes de correr las migraciones — en GitHub Actions usar `options: --health-cmd "mysqladmin ping"` en el service container.
- **`composer update` cambia versiones sin advertir que hay conflictos y la app falla en runtime por incompatibilidad de API**: Composer resuelve satisfactoriamente el grafo de versiones pero la API del paquete cambió de forma incompatible entre minor versions. Causa: Composer no puede detectar breaking changes en la API del código, solo conflictos de versiones semánticas declarados en composer.json. Solución: después de `composer update`, ejecutar `composer why-not paquete/nombre version` para ver qué cambió; revisar el CHANGELOG del paquete antes de actualizar y ejecutar los tests de integración.

## Checklist de diagnóstico

- [ ] `php -v` — ¿versión correcta?
- [ ] `php -m` — ¿extensiones necesarias instaladas?
- [ ] `composer diagnose` — ¿Composer detecta problemas?
- [ ] `composer dump-autoload` — ¿autoload regenerado?
- [ ] ¿El namespace PSR-4 coincide con la ruta del archivo (case-sensitive)?
- [ ] Para Laravel: `php artisan optimize:clear` — ¿caches limpios?
- [ ] Para errores de sintaxis: ¿la versión de PHP soporta la sintaxis usada?
- [ ] `composer why-not paquete version` — ¿conflictos de dependencias?
