> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Contenedor de servicios

> Explicamos el mecanismo de inyección de dependencias con el contenedor de servicios de Laravel y las bases de los bindings.

## ¿Qué es el contenedor de servicios?

El contenedor de servicios de Laravel gestiona las dependencias de las clases y realiza la inyección de dependencias. Con "inyección de dependencias" nos referimos a "inyectar" en una clase las dependencias que necesita, ya sea a través del constructor o, según el caso, mediante métodos setter.

Fíjate en este ejemplo:

```php theme={null}
<?php

namespace App\Http\Controllers;

use App\Services\AppleMusic;
use Illuminate\View\View;

class PodcastController extends Controller
{
    /**
     * Crea una nueva instancia del controlador
     */
    public function __construct(
        protected AppleMusic $apple,
    ) {}

    /**
     * Muestra la información del podcast indicado
     */
    public function show(string $id): View
    {
        return view('podcasts.show', [
            'podcast' => $this->apple->findPodcast($id)
        ]);
    }
}
```

Aquí `PodcastController` necesita obtener un podcast desde una fuente como Apple Music. Por eso **inyectamos** un servicio capaz de obtener podcasts. Al inyectarlo, resulta muy fácil sustituirlo por un mock durante las pruebas.

<Info>
  Entender bien el contenedor de servicios es imprescindible para construir aplicaciones Laravel grandes. También ayuda si vas a contribuir al propio núcleo de Laravel.
</Info>

```mermaid theme={null}
flowchart TD
    A["Service provider<br>register()"] --> B["Contenedor de servicios<br>Registro de bindings"]
    B --> C{"Petición de resolución<br>make() / inyección automática"}
    C -- "Clase concreta" --> D["Resolución automática<br>por reflexión"]
    C -- "Interfaz" --> E["Se resuelve con la<br>implementación registrada"]
    D --> F["Crea la instancia<br>e inyecta en el constructor"]
    E --> F
```

## Resolución sin configuración

Si una clase solo depende de otras clases concretas (no de interfaces), no hace falta indicar al contenedor cómo resolverla. Por ejemplo, imagina este código en `routes/web.php`:

```php theme={null}
<?php

class Service
{
    // ...
}

Route::get('/', function (Service $service) {
    dd($service::class);
});
```

<Info>
  Este ejemplo define la clase en el archivo de rutas por motivos didácticos. En una aplicación real, define las clases de servicio en el directorio `app/Services`.
</Info>

Al acceder a la ruta, Laravel resuelve automáticamente la clase `Service` y la inyecta en el manejador. Puedes disfrutar de la inyección de dependencias sin ningún archivo de configuración.

Muchas de las clases que escribes en una aplicación Laravel (controladores, listeners de eventos, middleware, etc.) reciben sus dependencias por inyección automática a través del contenedor.

## Bindings

### Binding básico

La mayoría de bindings se registran dentro de un [service provider](/es/service-providers). Dentro de él accedes al contenedor con `$this->app`.

#### bind

Con `bind` registras un binding pasando el nombre de la clase/interfaz y una closure.

```php theme={null}
use App\Services\Transistor;
use App\Services\PodcastParser;
use Illuminate\Contracts\Foundation\Application;

$this->app->bind(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});
```

La closure recibe el propio contenedor como argumento y puedes usarlo para resolver sub-dependencias.

Si necesitas interactuar con el contenedor fuera de un service provider, usa la fachada `App`.

```php theme={null}
use App\Services\Transistor;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\App;

App::bind(Transistor::class, function (Application $app) {
    // ...
});
```

<Info>
  Las clases que no dependen de interfaces no necesitan ser registradas en el contenedor. El contenedor puede resolverlas automáticamente mediante reflexión.
</Info>

#### singleton

`singleton` registra un binding que se resuelve una única vez. Una vez resuelto, las llamadas posteriores al contenedor devuelven la misma instancia.

```php theme={null}
use App\Services\Transistor;
use App\Services\PodcastParser;
use Illuminate\Contracts\Foundation\Application;

$this->app->singleton(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});
```

#### instance

También puedes registrar una instancia ya existente con `instance`. Las llamadas posteriores devolverán siempre esa instancia.

```php theme={null}
use App\Services\Transistor;
use App\Services\PodcastParser;

$service = new Transistor(new PodcastParser);

$this->app->instance(Transistor::class, $service);
```

### Binding de interfaces a implementaciones

Una de las capacidades más potentes del contenedor es enlazar una interfaz con una implementación concreta. Imagina que tienes la interfaz `EventPusher` y la implementación `RedisEventPusher`.

```php theme={null}
use App\Contracts\EventPusher;
use App\Services\RedisEventPusher;

$this->app->bind(EventPusher::class, RedisEventPusher::class);
```

Con esto, el contenedor inyecta `RedisEventPusher` en las clases que necesitan una implementación de `EventPusher`. Solo tienes que tipar la interfaz en el constructor.

```php theme={null}
use App\Contracts\EventPusher;

/**
 * Crea una nueva instancia de la clase
 */
public function __construct(
    protected EventPusher $pusher,
) {}
```

<Tip>
  Depender de interfaces te permite cambiar la implementación sin modificar el código. Facilita las pruebas y los cambios futuros.
</Tip>

## Resolución automática (DI por type-hint)

Cuando el contenedor resuelve clases como controladores, listeners o middlewares, mira los type-hints del constructor e inyecta las dependencias automáticamente.

```php theme={null}
<?php

namespace App\Http\Controllers;

use App\Repositories\UserRepository;

class UserController extends Controller
{
    /**
     * Crea una nueva instancia del controlador
     */
    public function __construct(
        protected UserRepository $users,
    ) {}
}
```

Si `UserRepository` no depende de interfaces, no hace falta registrarlo en el contenedor. Basta con acceder a la ruta y el contenedor resolverá e inyectará las dependencias en el controlador.

## Resolver desde el contenedor

### El método make

Con `make` puedes resolver una instancia desde el contenedor.

```php theme={null}
use App\Services\Transistor;

$transistor = app()->make(Transistor::class);
```

Si alguna dependencia de la clase no se puede resolver desde el contenedor, usa `makeWith` para pasar argumentos adicionales.

```php theme={null}
$transistor = $this->app->makeWith(Transistor::class, ['id' => 1]);
```

### Inyección automática

En la práctica, casi nunca llamarás a `make` directamente. Basta con tipar las dependencias en el constructor de las clases que el contenedor resuelve (controladores, listeners, middleware...) y el contenedor las inyectará automáticamente.

## Relación entre facades y contenedor

Las facades de Laravel ofrecen una interfaz estática hacia objetos del contenedor. Por ejemplo, `Cache::get()` obtiene internamente el servicio `Cache` del contenedor y lo invoca.

```php theme={null}
use Illuminate\Support\Facades\Cache;

// Llamada usando la fachada
Cache::get('key');

// Llamada equivalente usando el contenedor
app('cache')->get('key');
```

Las facades son envoltorios cómodos alrededor del contenedor. Durante las pruebas puedes sustituir la fachada por un mock.

```php theme={null}
use Illuminate\Support\Facades\Cache;

Cache::shouldReceive('get')
    ->once()
    ->with('key')
    ->andReturn('value');
```

## Caso práctico de inyección por constructor

Veamos un patrón habitual en aplicaciones reales.

<Steps>
  <Step title="Definir la interfaz">
    ```php theme={null}
    <?php

    namespace App\Contracts;

    interface PaymentGateway
    {
        public function charge(int $amount, string $token): bool;
    }
    ```
  </Step>

  <Step title="Crear la clase de implementación">
    ```php theme={null}
    <?php

    namespace App\Services;

    use App\Contracts\PaymentGateway;

    class StripePaymentGateway implements PaymentGateway
    {
        public function charge(int $amount, string $token): bool
        {
            // Cobro con la API de Stripe...
            return true;
        }
    }
    ```
  </Step>

  <Step title="Registrar el binding en un service provider">
    ```php theme={null}
    use App\Contracts\PaymentGateway;
    use App\Services\StripePaymentGateway;

    $this->app->singleton(PaymentGateway::class, StripePaymentGateway::class);
    ```
  </Step>

  <Step title="Recibir la inyección en el controlador">
    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use App\Contracts\PaymentGateway;
    use Illuminate\Http\Request;

    class OrderController extends Controller
    {
        public function __construct(
            protected PaymentGateway $payment,
        ) {}

        public function store(Request $request)
        {
            $this->payment->charge(
                $request->amount,
                $request->payment_token
            );

            // ...
        }
    }
    ```
  </Step>
</Steps>

Con este patrón, si cambias de proveedor de pago (por ejemplo, sustituyes `Stripe` por otro), basta con cambiar el binding en un único lugar.

## Próximos pasos

<Card title="Service providers" icon="plug" href="/es/service-providers">
  Aprende a registrar bindings usando service providers.
</Card>


## Related topics

- [Ciclo de vida de la solicitud](/es/lifecycle.md)
- [Implementación de un guard de autenticación personalizado](/es/advanced/custom-auth-guard.md)
- [Estructura de aplicación en Laravel 11 y posteriores](/es/advanced/app-structure.md)
- [Service providers](/es/service-providers.md)
- [Manejo de errores](/es/error-handling.md)
