# Doc: Symfony Service Container & Dependency Injection (Symfony 7.x)

> Relevancia Wari: DT-006 (GrupoService y EventoService con demasiadas dependencias — síntoma de SRP violado)

## Configuración base (ya debería estar así)

```yaml
# config/services.yaml
services:
    _defaults:
        autowire: true
        autoconfigure: true

    App\:
        resource: '../src/'
        exclude: '../src/{Entity,Kernel.php}'
```

Con esto: todos los servicios en `src/` se registran automáticamente, con inyección automática por tipo.

## Inyección por constructor — siempre

```php
class EventoService
{
    public function __construct(
        private EntityManagerInterface $em,
        private TelegramService $telegram,
        private NotificacionService $notificaciones,
    ) {}
}
```

- Dependencias inmutables y visibles.
- Fáciles de mockear en tests.
- Nunca usar `$container->get()` ni `ServiceLocator` salvo casos justificados.

## Un servicio con muchas dependencias es una señal

Si un servicio necesita 6+ dependencias en el constructor, probablemente viola SRP.

```
# Señal de alarma: GrupoService con 10 dependencias
GrupoService(
    EntityManager,
    GrupoRepository,
    UsuarioRepository,
    TelegramService,
    MailService,
    NotificacionService,
    AuditService,
    ImageService,
    GrupoPermisoService,
    UsernameTagService,
)
```

Solución: dividir en servicios de responsabilidad única.
- `GrupoCreacionService` — crear y configurar grupos.
- `GrupoMembresiaService` — gestionar miembros e invitaciones.
- `GrupoNotificacionService` — orquestar notificaciones de grupo.

## Binding global para valores de entorno

```yaml
services:
    _defaults:
        bind:
            $adminEmail: '%env(ADMIN_EMAIL)%'
            $uploadsDir: '%kernel.project_dir%/public/uploads'
```

Evita repetir `%env(...)%` en cada servicio que lo necesite.

## Múltiples implementaciones de la misma interfaz

```yaml
services:
    App\Service\TelegramNotifier:
        arguments:
            $transport: '@telegram.transport.default'

    App\Service\MailNotifier:
        arguments:
            $transport: '@mailer.transport.default'

    # Elegir cuál inyectar por defecto
    App\Contract\NotifierInterface: '@App\Service\TelegramNotifier'
```

O con atributo:
```php
public function __construct(
    #[Autowire(service: 'App\Service\TelegramNotifier')]
    private NotifierInterface $notifier,
) {}
```

## Servicios solo en entorno concreto

```php
use Symfony\Component\DependencyInjection\Attribute\When;

#[When(env: 'dev')]
class DebugTelegramService implements TelegramServiceInterface {}
```

## Debug útil

```bash
# Ver todos los servicios registrados
php bin/console debug:container

# Ver qué se puede autowirear
php bin/console debug:autowiring

# Validar el contenedor antes de desplegar
php bin/console lint:container
```

## Errores comunes

| Error | Corrección |
|---|---|
| Servicio con 6+ dependencias | Dividir en servicios más pequeños |
| `$container->get()` en servicio | Inyectar la dependencia directa por constructor |
| Sin type hint en constructor | Symfony no puede autowirear sin tipo |
| Servicio público innecesario | Dejar privado (por defecto); acceder solo por inyección |
| Lógica de inicialización en constructor | Moverla a un método `setUp()` o al primer uso |
