Inyección de dependencias
Tags: laravel, php
Published: 2020-10-28 00:44:17

La inyección de dependencias nos permite modularizar código, evitar repetir código y también evitar el acoplamiento de otras clases.

Supongamos que tenemos un servicio que nos permite envíar diferentes tipos de mensajes hacia un destino en particular, lo vamos a llamar "notificador", este notificador contiene adentro las funcionalidades para poder envíar un mensaje por correo electrónico, o por Whatsapp. Ahora, para poder acceder a enviar con cualquiera de los dos metodos de envío, tenemos que instanciarlos y llamar al metodo enviar de cada uno para poder enviar el mensaje, imaginemos que tenemos EnvioWhatsapp y EnvioCorreo y tenemos que instanciarlos:

```php
class Notificador {
    public function enviar($whatsapp, $correo){
        $envioWhatsapp = new EnvioWhatsapp();
        $envioCorreo = new EnvioCorreo();
        
        $envioWhatsapp->enviar($whatsapp);
        $envioCorreo->enviar($correo);
    }
```

Entonces ya podemos envíar mensajes a través del método envíar:

```php
$enviar = new Notificador();
$enviar->enviar(+54112344555, correo@correo.com);
-------------------MENSAJES ENVIADOS----------------------
```
El problema de esto es que estamos instanciando los objetos cada vez que los necesitamos usar en alguna clase, por lo que si en el futuro EnvioCorreo y EnvioWhatsapp cambia, tendríamos que cambiar el código en cada uno de los lugares en los que lo estamos usando. La solución para esto es sencillo, crear un contendor que esté "subscripto" a cada una de las clases y nos proporcione los métodos correspondientes para poder usarlo en el lugar que nosotros queramos. 

Hay varias formas de hacerlo y lo voy a mostrar con un ejemplo real, las mas conocidas son la inyección de dependencias a través del constructor:

- Tengo un blog en donde necesitamos crear posteos, editarlos y eliminarlos, entonces vamos a crear un contenedor que esté subscripto a la clase posteo, que nos va a permitir crear un nuevo post en la base de datos:

```php
<?php
namespace App\Repositories;
use Illuminate\Support\Facades\Auth; 
use App\Models\Post;
use App;
use DB;

class Postrepository{
    public function create($data){
        $user = Auth::user();
        $post = new Post;
        $post->post_title = $data->post_title;
        $post->post_content = $data->post_content;
        $post->post_image_1 = $data->post_image_1;
        $post->post_image_2 = $data->post_image_2;
        $post->user_id = $user->id;
        $post->save();
    }

    public function update($id, $data){
       $update =  DB::table('posts')->where('id', $id)->update([
            'post_title' => $data->post_title,
            'post_content' => $data->post_content,
            'post_image_1' => $data->post_image_1,
            'post_image_2' => $data->post_image_2,
        ]);
    }

    public function delete($id){
        $post = Post::find($id);
        $post->delete();
    }

    public function show($id){
        if($posts = Post::find($id)){
            echo $posts;
        }
        echo 'No existe el post';
    }
}

?>
```

Entonces lo único que nos falta es inyectar las dependencias de este contenedor que nos permite crear, eliminar y editar post adentro de nuestro controlador:

```php
<?php

namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; 
use App\Repositories\Postrepository;
use App\Models\Post;

class PostController extends Controller
{
    private $postRepository;

    public function __construct(Postrepository $repository){
        $this->postRepository = $repository;
    }

    public function create(Request $request){
        $post = $this->postRepository;
        $post->create($request);
        return redirect('/home');
    }

    public function update(Request $request, $id){
        $post = $this->postRepository;
        $post->update($id ,$request);
        return redirect('/home');
    }


    public function delete(Request $request, $id){
        $post = $this->postRepository;
        $post->delete($id);
        return redirect('/home');
    }

    public function show($id){
        $post = $this->postRepository;
        $post->show($id);
    }
}
```

Y vemos como a través de estas pocas líneas podemos acceder a todos los métodos para utilizar con el crud:

```php
 private $postRepository;

    public function __construct(Postrepository $repository){
        $this->postRepository = $repository;
    }
```

la explicación es fácil, el constructor va a iyectar todos los métodos del contendor adentro de la variable $repository y nosotros le pasamos esos métodos a la variable $postRepository para que pueda ser usada en cualquier parte del controlador:

Como en el método create por ejemplo:

```php
public function create(Request $request){
        $post = $this->postRepository;
        $post->create($request);
        return redirect('/home');
    }
```

La segunda opción más conocida es inyectar las dependencias directamente en los métodos, y esto es una forma muy facil, creamos un nuevo controlador e inyectamos directamente en el método en el que necesitamos usar las dependencias:

```php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Post;
use App\Repositories\Postrepository;

class NuevoController extends Controller
{
    public function porMetodos(Postrepository $post){
       return $post->show(5);
    }
}
```

RESULTADO:
```json
{"post_title":"Titulo de prueba","post_content":"Producto de prueba para que lo puedas comprar","post_image_1":"imagen1.jpg","post_image_2":"imagen2.jpg","user_id":"1","id":5,"created_at":null,"updated_at":null}
```
Y eso es todo, espero que les sirva.