Implementing Laravel (ES)

Documentos relacionados
CITRIX Citrix Application Streaming

Curso de Java POO: Programación orientada a objetos

Manual CMS Mobincube

Guía de uso del Cloud Datacenter de acens

PowerPoint 2010 Modificar el diseño de las diapositivas

MANUAL DE AYUDA TAREA PROGRAMADA COPIAS DE SEGURIDAD

Creación paso a paso de Formularios con Google (Parte I) (AKA: no corrijo nunca más!)

Programación Orientada a Objetos con Java

Archivo de correo con Microsoft Outlook contra Exchange Server

GUÍA RED SOCIAL FACEBOOK

PANEL DE CONTROL (Zona de Administración) MANUAL DE USO Por conexanet. Revisión 1.1 Fecha

PHP y MySQL. Inicio: - Herencia - Palabra clave Final - Polimorfismo - Type Hinting - Abstracción de clases

G R U P O S INDICE Cómo crear una cuenta en ARQA? Cómo tener un grupo en ARQA? Secciones y funcionalidades de los grupos Configuración del grupo

Manual para la utilización de PrestaShop

MANUAL PARA GESTIÓN DE INCIDENCIAS INFORMÁTICAS

Practica A. Crear y Administrar Grupos

DESCARGA E INSTALACIÓN DE LA DOCUMENTACIÓN PARA LAS CLASES DEL API DE JAVA. CONSULTAR EN LOCAL O EN INTERNET? (CU00910C)

Uso del Programa Gantt Project

En la siguiente imagen se muestra la pantalla principal del portafolio de un usuario que será utilizado para explicar cada aspecto del mismo.

Práctica 5. Curso

Introducción a la Programación Orientada a Objetos

La plantilla propone aprovechar esta estructura en común y sólo modificar el contenido del área del documento que sea diferente.

2.2.- Paradigmas de la POO

Toda base de datos relacional se basa en dos objetos

ÍTEMS DEL MENÚ CREACIÓN Y GESTIÓN (Última revisión: lunes, 9 de marzo de 2009)

App para realizar consultas al Sistema de Información Estadística de Castilla y León

Propuesta de Portal de la Red de Laboratorios Virtuales y Remotos de CEA

MANUAL DE USUARIO APLICACIÓN SYSACTIVOS

15 CORREO WEB CORREO WEB

En términos generales, un foro es un espacio de debate donde pueden expresarse ideas o comentarios sobre uno o varios temas.

Descripción del tutorial. Contenidos.

PLANTILLAS EN MICROSOFT WORD

Unidad Didáctica 12. La publicación

Cómo instalar fácilmente tu WordPress tras contratar un hosting en Hostalia

JavaScript como Orientación a Objetos

COPIAS DE SEGURIDAD CON COBIAN BACKUP INSTALACIÓN Y CONFIGURACIÓN

Crear la base de datos antes de la instalación de Wordpress.

AGREGAR UN EQUIPO A UNA RED Y COMPARTIR ARCHIVOS CON WINDOWS 7

2. Seleccione OneDrive en la parte superior de los sitios de SharePoint u Office 365 de su organización.

Proceso de cifrado. La fortaleza de los algoritmos es que son públicos, es decir, se conocen todas las transformaciones que se aplican al documento

Internet Information Server

PHP Perfect SQL v1.0 (SQL perfectas en PHP)

Tutorial: Primeros Pasos con Subversion

Manual de uso de la plataforma para monitores. CENTRO DE APOYO TECNOLÓGICO A EMPRENDEDORES -bilib

Manual de NVU Capítulo 4: Los enlaces

GMAIL (avanzado) 1. Accede a la web de Gmail, Te destacamos las funcionalidades que vamos a enseñarte a. 2. Vamos a enseñarte a:

Instalar XAMP en modo gráfico

Resumen ÁREA DE FACTURACIÓN::INFORMES::Pedidos Detalle Resumen ÁREA DE

SAP Business Workflow

Creación de Funciones de Conducción

Hostaliawhitepapers. Las ventajas de los Servidores dedicados. Cardenal Gardoki, BILBAO (Vizcaya) Teléfono:

LABORATORIO Nº 3 PRÁCTICA DE FUNCIONES EN MICROSOFT EXCEL

Uso de Visual C++ Pre-Practica No. 3

Base de datos en Excel

Programación en Java. Programación en OO

BETA. Sacándole Partido a JUnit. Mocking. formacion@iwt2.org

Ejercicios - Persistencia en Android: ficheros y SQLite

Programa diseñado y creado por Art-Tronic Promotora Audiovisual, S.L.

Guía de uso del sistema CV-Online

Patrones Creacionales Builder. Patrones Creacionales Abstract Factory. Patrones Creacionales Singleton. Patrones Creacionales Prototype

La ventana de Microsoft Excel

QUÉ ES UN SERVIDOR Y CUÁLES SON LOS PRINCIPALES TIPOS DE SERVIDORES? (PROXY, DNS, WEB, FTP, SMTP, ETC.) (DV00408A)

CAPITULO 4. Requerimientos, Análisis y Diseño. El presente capítulo explica los pasos que se realizaron antes de implementar

Libro Ágil Ilustrado. a disfrutar el camino! Pablo Tortorella. Este libro está a la venta en

Programación I: Funciones y módulos

MANUAL DE AYUDA MODULO TALLAS Y COLORES

Sitios remotos. Configurar un Sitio Remoto

1.- INTRODUCCIÓN 2.- PARÁMETROS

Manejo de versiones 392

Creando una webquests

TUTORIAL (TRANSLATE.CLASS)

Tutorial Básico de vbscript

PREPARANDO EL ENTORNO DE DESARROLLO PARA PROGRAMAR EN PHP. DESCARGAR E INSTALAR NOTEPAD++ (CU00808B)

TEMA 4: EMPEZANDO A NAVEGAR ESCUELA UNIVERSITARIA DE INFORMÁTICA. Raúl Martín Martín

GUÍA PARA LA INSTALACIÓN Y USO DE WORDPRESS BY MASTERHACKS. Guía de instalación y uso de Wordpress Página 1

COMO CONFIGURAR UNA MAQUINA VIRTUAL EN VIRTUALBOX PARA ELASTIX

Web Publishing con LabVIEW (I)

GUIA APLICACIÓN DE SOLICITUDES POR INTERNET. Gestión de Cursos, Certificados de Aptitud Profesional y Tarjetas de Cualificación de Conductores ÍNDICE

Implementación de widgets Avaibook en Blogger

INDICE. 1. Introducción El panel Entities view El panel grafico Barra de botones Botones de Behavior...

Qué es Google Calendar? Qué se puede hacer en Google Calendar?

Curso Internet Básico - Aularagon

TABLA DE DECISION. Consideremos la siguiente tabla, expresada en forma genérica, como ejemplo y establezcamos la manera en que debe leerse.

Curso de PHP con MySQL Gratis

Manual de iniciación a

CVS Concurrent Versions System Manual de Usuario

CONFEDERACIÓN DE EMPRESARIOS DE MÁLAGA

PROGRAMACIÓN ORIENTADA A OBJETOS Master de Computación. II MODELOS y HERRAMIENTAS UML. II.2 UML: Modelado de casos de uso

Manual de Usuario. Facebook

MANUAL COPIAS DE SEGURIDAD

TUTORIAL SOBRE CÓMO CREAR Y GESTIONAR UN BLOG CON BLOGGER

Capitulo 5. Implementación del sistema MDM

LECCION 5. Herramientas de Pintura y Edición Parte II. Crear formas de Pincel

SOLUCIÓN CASO GESTIÓN DE PERSONAL I

Introducción a Moodle

En cualquier caso, tampoco es demasiado importante el significado de la "B", si es que lo tiene, lo interesante realmente es el algoritmo.

Catoira Fernando Fullana Pablo Rodriguez Federico [MINERIA DE LA WEB] Proyecto Final - Informe Final

Guia de realización de un GIG personal en nuestra página web (

Transcripción:

Implementing Laravel (ES) implementando Laravel Chris Fidao y Judas Borbón Este libro está a la venta en http://leanpub.com/implementinglaravel-es Esta versión se publicó en 2013-10-16 This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and many iterations to get reader feedback, pivot until you have the right book and build traction once you do. 2013 Chris Fidao y Judas Borbón

Índice general Conceptos fundamentales................................. 1 El contenedor........................................... 2 Uso básico............................................ 2 Algo más avanzado....................................... 3 Inversión de control....................................... 3 Uso en una situación real.................................... 5 Inyección de dependencias.................................... 7 Qué es la inyección de dependencias?............................. 7 Agregando dependencias a los controladores......................... 8 Interfaces como dependencias................................. 9 Por qué la inyección de dependencias?............................ 11 En resúmen............................................ 15

Conceptos fundamentales A lo largo del libro usaremos algunas de las características más poderosas de Laravel. Antes de comenzar, es importante conocer por lo menos el contenedor de Laravel y cómo facilita el uso de la Inyección de Dependencias. Este capítulo aborda el contenedor de Laravel, su uso de la Inversión de Control y la Inyección de Dependencias.

El contenedor La clase Illuminate\Foundation\Application es la que encapsula todo Laravel. Esta clase es un contenedor - puede contener datos, objetos, clases y hasta funciones anónimas. Uso básico Para ver cómo funciona el contenedor, hagamos un ejercicio en el archivo de rutas. El contenedor de Laravel implementa ArrayAccess, así que podemos acceder a él como un arreglo. Veamos cómo acceder a manera de arreglo asociativo. Archivo: app/routes.php 1 Route::get('/container', function() 2 { 3 // Se obtiene la instancia de la aplicación 4 $app = App::getFacadeRoot(); 5 6 $app['some_array'] = array('foo' => 'bar'); 7 8 var_dump($app['some_array']); 9 }); Si nos dirigimos a la ruta /container, obtendremos el siguiente resultado: 1 array (size=1) 2 'foo' => string 'bar' (length=3) Como podemos ver, aunque Application es una clase con atributos y métodos, también se puede acceder como si fuera un arreglo! Fachadas Confundido con lo que hace App::getFacadeRoot()? La clase App es una fachada. Esto nos permite usarla en cualquier lugar, de manera estática. Sin embargo, en realidad no se trata de una clase estática. getfacaderoot obtiene la verdadera instancia de la clase, lo cual tuvimos que hacer para usarla como un arreglo en el ejemplo anterior. Se puede ver esta y otras fachadas en el espacio de nombres Illuminate\Support\Facades.

El contenedor 3 Algo más avanzado Hagamos algo más elegante con el contenedor y asignémosle una función anónima: Archivo: app/routes.php 1 Route::get('/container', function() 2 { 3 // Se obtiene la instancia de la aplicación 4 $app = App::getFacadeRoot(); 5 6 $app['say_hi'] = function() 7 { 8 return "Hello, World!"; 9 }; 10 11 return $app['say_hi']; 12 }); De nuevo, si nos dirigimos a la ruta /container veremos lo siguiente: 1 Hello, World! Aunque en apariencia es algo muy simple, en realidad es algo bastante poderoso. De hecho, es la base de cómo los paquetes Illuminate interactúan unos con otros para hacer funcionar al framework Laravel. Más adelante veremos cómo los Proveedores de Servicios vinculan elementos al contenedor, uniendo los diferentes paquetes Illuminate. Inversión de control La clase Container de Laravel tiene más cosas bajo la manga además de actuar como un arreglo. También funciona como un contenedor de Inversión de Control. La Inversión de Control es una técnica que permite definir cómo una aplicación implementa una clase o interfaz. Por ejemplo, si nuestra aplicación depende de la interfaz FooInterface y queremos implementar la clase ConcreteFoo, es en el contenedor de Inversión de Control donde hay que definir la implementación. Veamos un ejemplo básico de cómo funciona usando la ruta /container una vez más. Primero vamos a preparar algunas clases - una interfaz y una clase que la implemente. Para mantener el ejemplo sencillo, ambas pueden estar en el archivo app/routes.php:

El contenedor 4 Archivo: app/routes.php 1 interface GreetableInterface { 2 3 public function greet(); 4 5 } 6 7 class HelloWorld implements GreetableInterface { 8 9 public function greet() 10 { 11 return 'Hello, World!'; 12 } 13 } Ahora usemos estas clases junto con el contenedor y veamos qué sucede. Primero quiero presentarles el concepto de vinculación. Archivo: app/routes.php 1 Route::get('/container', function() 2 { 3 // Se obtiene la instancia de la aplicación 4 $app = App::getFacadeRoot(); 5 6 $app->bind('greetableinterface', function() 7 { 8 return new HelloWorld; 9 }); 10 11 $greeter = $app->make('greetableinterface'); 12 13 return $greeter->greet(); 14 }); En lugar de acceder como arreglo usando $app['greetableinterface'] hemos usado el método bind(). Esto hace uso del contenedor de Inversión de Control de Laravel para devolver la clase HelloWorld cada vez que se solicita GreetableInterface.

El contenedor 5 De este modo es posible intercambiar implementaciones! Por ejemplo, en lugar de HelloWorld, podríamos crear una implementación llamada GoodbyeCruelWorld y hacer que el contenedor la devuelva cada que se solicite GreetableInterface. Esto encamina nuestras aplicaciones hacia la mantenibilidad. Al usar el contenedor, podemos (de forma ideal) intercambiar implementaciones en un solo lugar sin afectar otras áreas de la aplicación. Uso en una situación real Dónde hay que colocar estas vinculaciones? Si no queremos saturar los archivos start.php, filters.php, routes.php, entonces podemos hacer uso de los Proveedores de Servicios. Los Proveedores de Servicios sirven específicamente para registrar vinculaciones en el contenedor de Laravel. De hecho, casi todos los paquetes Illuminate usan un Proveedor de servicios justo para eso. Veamos un ejemplo de cómo los Proveedores de Servicios se usan dentro de un paquete Illuminate. Vamos a examinar el paquete de paginación. Primero, el método register() del Proveedor de Servicios de paginación: Illuminate\Pagination\PaginationServiceProvider.php 1 public function register() 2 { 3 $this->app['paginator'] = $this->app->share(function($app) 4 { 5 $paginator = new Environment( 6 $app['request'], 7 $app['view'], 8 $app['translator'] 9 ); 10 11 $paginator->setviewname( 12 $app['config']['view.pagination'] 13 ); 14 15 return $paginator; 16 }); 17 } El método register() se invoca automáticamente en cada uno de los Proveedores de Servicios alojados en el archivo app/config/app.php.

El contenedor 6 Entonces, qué es lo que ocurre en el método register()? Primero que nada, se registra la instancia del paginador en el contenedor. Esto hará que $app['paginator'] y App::make('paginator') estén disponibles en otras áreas de la aplicación. Luego, se define una instancia paginator como resultado del valor devuelto por una función anónima, tal y cómo lo hicimos en el ejemplo say_hi. No hay que confundir el uso de $this->app->share(). El método Share simplemente hace que la función anónima pueda usarse como un singleton (instancia única), similar a llamar a $this->app->instance('paginator', new Environment). La función anónima crea un objeto Pagination\Environment, lo configura y lo devuelve. Tal vez ya lo hayan notado, pero el Proveedor de Servicios crea otras vinculaciones en la aplicación! La clase PaginationEnvironment claramente accede a ciertas dependencias mediante su constructor - un objeto para peticiones $app['request'], un objeto para vistas $app['view'] y un traductor $app['translator']. Por suerte, estas vinculaciones son creadas en otros paquetes Illuminate y se definen en distintos Proveedores de Servicios. Podemos observar entonces cómo los diferentes paquetes Illuminate interactúan entre sí. Al encontrarse vinculados al contenedor de la aplicación, se pueden utilizar en otros paquetes ( o en nuestro propio código!) sin que nuestro código quede atado a una clase en particular.

Inyección de dependencias Ahora que hemos visto el funcionamiento del contenedor, veamos cómo podemos usarlo para implementar la Inyección de Dependencias en Laravel. Qué es la inyección de dependencias? La Inyección de Dependencias es el acto de agregar (inyectar) cualquier dependencia a una clase, en lugar de instanciarla en algún lugar dentro de ella. Es común definir las dependencias en el constructor como parámetros de un tipo específico. Tomen como ejemplo el siguiente constructor: 1 public function construct(helloworld $greeter) 2 { 3 $this->greeter = $greeter; 4 } Al definir el parámetro de tipo HelloWorld, indicamos explícitamente que se trata de una dependencia de la clase. Esto es lo contrario a la instanciación directa: 1 public function construct() 2 { 3 $this->greeter = new HelloWorld; 4 } Si se preguntan para qué se usa la Inyección de Dependencias, esta respuesta de Stack Overflow¹ es un buen lugar para empezar. Explicaré algunos otros de sus beneficios en ejemplos subsecuentes. Enseguida, veremos un ejemplo de Inyección de Dependencias en acción, usando el contenedor de Inversión de Control de Laravel. ¹http://stackoverflow.com/questions/130794/what-is-dependency-injection

Inyección de dependencias 8 Agregando dependencias a los controladores Este es un caso de uso común en Laravel. Normalmente, cuando un controlador requiere de ciertas clases en el constructor, es necesario agregar esas dependencias cuando se crea la clase. Sin embargo, qué sucede cuando se definen dependencias en un controlador de Laravel? Tendríamos que instanciar el controlador en alguna parte: 1 $crtl = new ContainerController( new HelloWorld ); Muy bien, pero en Laravel no es necesario instanciar el controlador directamente - el enrutador se encarga de eso. Aún así, es posible inyectar dependencias en el controlador con el uso del contenedor de Laravel! Siguiendo con las mismas clases GreetableInterface y HelloWorld de ejemplos anteriores, imaginemos que vinculamos a un controlador la ruta /container: Archivo: app/routes.php 1 interface GreetableInterface { 2 3 public function greet(); 4 5 } 6 7 class HelloWorld implements GreetableInterface { 8 9 public function greet() 10 { 11 return 'Hello, World!'; 12 } 13 } 14 15 Route::get('/container', 'ContainerController@container); Ahora en el controlador podemos establecer HelloWorld como parámetro:

Inyección de dependencias 9 Archivo: app/controllers/containercontroller.php 1 <?php 2 3 class ContainerController extends BaseController { 4 5 protected $greeter; 6 7 // Dependencia: HelloWorld 8 public function construct(helloworld $greeter) 9 { 10 $this->greeter = $greeter; 11 } 12 13 public function container() 14 { 15 return $this->greeter->greet(); 16 } 17 18 } Si nos dirigimos a la ruta /container deberíamos ver, una vez más: 1 Hello, World! Noten que NO vinculamos nada al contenedor. Simplemente funcionó - una instancia de tipo HelloWorld se pasó como parámetro al controlador! Esto se debe a que el contenedor de Inversión de Control de Laravel intenta resolver automáticamente cualquier dependencia que se haya definido en el constructor de un controlador. Laravel inyectará las dependencias por nosotros! Interfaces como dependencias No hemos terminado aún. Esta es la parte hacia donde queríamos llegar! Qué tal si en lugar de especificar HelloWorld como dependencia del controlador especificáramos la interfaz GreetableInterface? Veamos cómo quedaría:

Inyección de dependencias 10 Archivo: app/controllers/containercontroller.php 1 <?php 2 3 class ContainerController extends BaseController { 4 5 protected $greeter; 6 7 // Dependencia: GreetableInterface 8 public function construct(greetableinterface $greeter) 9 { 10 $this->greeter = $greeter; 11 } 12 13 public function container() 14 { 15 echo $this->greeter->greet(); 16 } 17 18 } Si intentamos ejecutarlo obtendremos un error: 1 Illuminate\Container\BindingResolutionException: 2 Target [GreetableInterface] is not instantiable Por supuesto que GreetableInterface no se puede instanciar, se trata de una interfaz. Sin embargo, podemos ver que Laravel intenta instanciarla con tal de resolver la dependencia de la clase. Solucionemos eso - usaremos el método bind() del contenedor para indicarle a Laravel que utilice una instancia de HelloWorld cuando el contenedor descubra que nuestro controlador depende de una instancia de GreetableInterface:

Inyección de dependencias 11 Archivo: app/routes.php 1 interface GreetableInterface { 2 3 public function greet(); 4 5 } 6 7 class HelloWorld implements GreetableInterface { 8 9 public function greet() 10 { 11 return 'Hello, World!'; 12 } 13 } 14 15 // Vinculamos HelloWorld para cuando se requiera 16 // una instancia de GreetableInterface! 17 App::bind('GreetableInterface', 'HelloWorld'); 18 19 Route::get('/container', 'ContainerController@container); Ahora ejecutemos la ruta /container para ver de nuevo el mensaje Hello, World! Noten que no utilizamos una función anónima para vincular HelloWorld - Es posible simplemente indicar el nombre de la clase que deseamos. Una función anónima es útil cuando la implementación tiene a su vez sus propias dependencias, las cuales hay que pasar en su constructor. Por qué la inyección de dependencias? Por qué íbamos a querer especificar una interfaz como dependencia en lugar de una clase concreta? Lo queremos así porque necesitamos que cualquier clase que le pasemos al constructor sea una subclase de la interfaz. De esta manera podemos usar cualquier implementación - el método que necesitamos siempre estará disponible. Dicho de otra manera: podemos cambiar la implementación a voluntad, sin afectar otras secciones de nuestra aplicación. Aquí tenemos un ejemplo. Algo que he tenido que hacer muchas veces en aplicaciones reales.

Inyección de dependencias 12 No copien y peguen el código de este ejemplo. He omitido algunos detalles de configuración para simplificarlo, tales como claves API. Supongamos que nuestra aplicación envía correos utilizando AWS de Amazon. Para lograrlo, hemos definido una interfaz Emailer y una implementación, llamada AwsEmailer: 1 interface Emailer { 2 3 public function send($to, $from, $subject, $message); 4 } 5 6 class AwsEmailer implements Emailer { 7 8 protected $aws; 9 10 public function construct(awssdk $aws) 11 { 12 $this->aws = $aws; 13 } 14 15 public function send($to, $from, $subject, $message) 16 { 17 $this->aws->addto($to) 18 ->setfrom($from) 19 ->setsubject($subject) 20 ->setmessage($message); 21 ->sendemail(); 22 } 23 } Vinculamos Emailer a la implementación AwsEmailer: 1 App::bind('Emailer', function() 2 { 3 return new AwsEmailer( new AwsSDK ); 4 }); Un controlador usa como dependencia la interfaz Emailer:

Inyección de dependencias 13 Archivo: app/controllers/emailcontroller.php 1 class EmailController extends BaseController { 2 3 protected $emailer; 4 5 // Dependencia: Emailer 6 public function construct(emailer $emailer) 7 { 8 $this->emailer = $emailer; 9 } 10 11 public function email() 12 { 13 $this->emailer->send( 14 'ex-to@example.com', 15 'ex-from@example.com', 16 'Peanut Butter Jelly Time!', 17 "It's that time again! And so on!" 18 ); 19 20 return Redirect::to('/'); 21 } 22 23 } Ahora supongamos que, más adelante, nuestra aplicación crece y necesita más funcionalidad de la que provee AWS. Después de investigar y evaluar opciones decidimos usar SendGrid. Cómo procedemos a modificar la aplicación para que use SendGrid? Ya que hemos usado interfaces y el contenedor de Laravel, hacer el cambio es muy fácil! Primero hay que crear una implementación de Emailer que haga uso de SendGrid.

Inyección de dependencias 14 1 class SendGridEmailer implements Emailer { 2 3 protected $sendgrid; 4 5 public function construct(sendgridsdk $sendgrid) 6 { 7 $this->sendgrid = $sendgrid; 8 } 9 10 public function send($to, $from, $subject, $message) 11 { 12 $mail = $this->sendgrid->mail->instance(); 13 14 $mail->addto($to) 15 ->setfrom($from) 16 ->setsubject($subject) 17 ->settext( strip_tags($message) ) 18 ->sethtml($message) 19 ->send(); 20 21 $this->sendgrid->web->send($mail); 22 } 23 } Después ( y por último!), hay que indicarle a la aplicación que use SendGrid en lugar de Aws. Como hemos utilizado bind() en el contenedor, cambiar la implementación de Emailer de AwsEmailer a SendGridEmailer es tan sencillo como hacer esta única modificación: 1 // De 2 App::bind('Emailer', function() 3 { 4 return new AwsEmailer( new AwsSDK ); 5 }); 6 7 // A 8 App::bind('Emailer', function() 9 { 10 return new SendGridEmailer( new SendGridSDK ); 11 }); Noten que hemos hecho todo esto sin cambiar una sola línea de código en otro lugar de la aplicación. Al requerir el uso de la interfaz Emailer como dependencia, se garantiza que cualquier clase que se inyecte tendrá disponible el método send().

Inyección de dependencias 15 Podemos observar esto en nuestro ejemplo. El controlador aún hace la llamada a $this->emailer->send() sin requerir ninguna modificación al hacer el cambio de implementación de AwsEmailer a SendGridEmailer. En resúmen. La Inyección de Dependencias y la Inversión de Control son patrones utilizados una y otra vez en el desarrollo con Laravel. Cómo veremos después, vamos a definir muchas interfaces para hacer nuestro código más fácil de mantener y para facilitar las pruebas. El contenedor de Inversión de Control de Laravel lo facilita.