DEV Community

Nahuel Segovia
Nahuel Segovia

Posted on

Inyección de dependencias

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:

class Notificador {
    public function enviar($whatsapp, $correo){
        $envioWhatsapp = new EnvioWhatsapp();
        $envioCorreo = new EnvioCorreo();

        $envioWhatsapp->enviar($whatsapp);
        $envioCorreo->enviar($correo);
    }
Enter fullscreen mode Exit fullscreen mode

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

$enviar = new Notificador();
$enviar->enviar(+54112344555, correo@correo.com);
-------------------MENSAJES ENVIADOS----------------------
Enter fullscreen mode Exit fullscreen mode

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
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';
    }
}

?>
Enter fullscreen mode Exit fullscreen mode

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

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

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

 private $postRepository;

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

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:

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

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

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

RESULTADO:

{"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}
Enter fullscreen mode Exit fullscreen mode

Y eso es todo, espero que les sirva.

Top comments (2)

Collapse
 
alelazcano profile image
Alejandro Lazcano

Excelente aporte y muy clara la explicación. Gracias

Collapse
 
nahuelsegovia profile image
Nahuel Segovia

Gracias a vos por leerme :)