Route Model Binding

Recientemente se nos creo la inquietud del trabajo repetitivo de consultar la BD cuando se inyecta un ID en una ruta o la acción de un controlador. Si eres fiel seguidor de las buenas prácticas de desarrollo de software, debes saber que existe un principio llamado DRY (Don’t Repeat Yourself), que básicamente nos alienta a reducir la repetición de información de todo los tipos.

Normalmente, en una acción de actualización, supongamos para el caso en estudio, se requiere actualizar una factura. Un definición de la ruta sería la siguiente:

Route::get(‘invoice/edit/{id}’, ‘InvoiceController@edit’);

Ahora bien, la acción del controlador podría ser codificada de la siguiente forma:


/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return Response
*/
public function edit($id)
{
$invoice = invoice::findOrFail($id);

$this->authorize(‘edit’, $invoice);

return view(‘invoices.edit’)
->with(‘invoice’, $invoice);
}

Esto nos refiere, que para cada acción en particular, tenemos que inyectar el ID, luego obtener el modelo relacionado al ID proporcionado. Laravel nos provee otra forma de resolver este dilema, con el Route Model Binding que implementa un método conveniente, automáticamente podemos inyectar la instancia del modelo directamente en las rutas.

En otras palabras, en lugar de inyectar el ID de la factura, se puede inyectar la instancia del modelo Invoice que corresponde al ID dado.

Implicita

Existe la forma implícita, en la cual Laravel automáticamente resuelve el modelo Eloquent definido en las rutas o las acciones del controlador, cuyos nombres de variable sugeridos por tipo coincidan con el nombre de segmento de la ruta, por ejemplo:

Route::get('api/users/{user}', function (App\User $user) {
return $user->email;
});

Como la variable $user es declarada del tipo modelo Eloquent App\User y el nombre de la variable $user corresponde al valor de segmento URI {user}, Laravel automáticamente inyectará la instancia del modelo que tenga un ID igual al que se envía en URI. Si por algún motivo no se encuentra el ID, se lanzará un error 404.

Explicita

Para registrar la forma explicita, hay que usar el método model en la ruta y especificar la clase para el parámetro dado. Se puede definir las formas explicitas en el método boot de la clase RouteServiceProvider.


public function boot()
{
parent::boot();

Route::model(‘user’, App\User::class);
}

Ahora, definimos una ruta que contenga un parámetro llamado {user}:

Route::get(‘profile/{user}’, function (App\User $user) {
//
});

Asi, como hemos atado el parámetro {user} al model App\User, una instancia de User será inyectado a la ruta. Entonces, por ejemplo, se podría llamar la ruta profile/1, lo cual inyectará la instancia User desde la base de datos donde el ID sea 1. Al igual que la forma implícita, sino se encuentra una instancia para el ID dado, se lanzará un error HTTP 404.

Laravel Dusk

Cuando se escriben pruebas “end-to-end”, Laravel provee un abanico de metodos de ayuda, que hacen que sea fácil hacer clics en los enlaces, llenar campos de formularios e inclusive enviarlos. En el fondo, Laravel usa el componente Symfony BrowserKit para simular el comportamiento de un navegador web. Sin embargo, si la aplicación usa JavaSript y AJAX para cargar las paginas,   BrowserKit no es para ti.

Laravel Dusk es la nueva herramienta que es introducida a partir de Laravel 5.4 para resolver este problema.

Dusk es una herramienta de navegador para pruebas end-to-end en aplicaciones habilitadas con JavaScript. Este proporcionará la forma correcta de probar la iteraciones concernientes a una pagina web. En otras palabras, se puede usar Dusk para las acciones como clics en botones y enlaces, llenar formularios hasta incluso arrastrar y soltar!.

Para esto, Dusk esta utilizando “ChromeDrive” y “Facebook PHP-Webdriver” para realizar las pruebas end-to-end. Este puede trabajar con cualquier navegador “Selenium”, pero trae ChromeDrive por defecto que nos ayuda ahorrar las configuraciones previas del JDK o Selenium, lo que lo hace muy fácil de usar sin la necesidad de ir a través del proceso de arranque de Selenium e iniciar su servidor cada vez que se necesiten correr las pruebas. Ademas, segun Taylor Otwell, las pruebas en Dusk son muchas mas rápidas que en el Selenium.

En este orden de ideas, Dusk es mas natural que un BrowserKit; no se tiene que esperar a que algo “termine” o usar sleeping  y pausing mientras se espera que las cosas aparezcan. En contraste, Dusk permite aguantar a que ciertas condiciones sean verdaderas en tu código JavaScript o esperar a que los selectores CSS estén disponibles para tener una mejor manera para probar las aplicaciones con JavaScript habilitado.

Además, Dusk tiene entre otras características, guardar un captura de pantalla en las pruebas fallidas automáticamente. De esta forma, se puede observar como estaba la pagina cuando las cosas fueron mal.

Otra característica es que provee de método de ayuda como loginAs, el cual permite asignar una instancia de un usuario de la aplicación, con esto accionará el acceso de usuario, facilitando el trabajo en los URL que se necesiten la autenticación.

También, se permite abrir múltiple ventanas del navegador por prueba, lo cuál es favorable cuando la aplicación tiene integración con sockets y es necesario un tipo de pruebas en estos escenarios. Asimismo, es posible abrir dos ventanas y interactuar con la primera y obtener los resultados en la segunda.

Incluso, Otwell ha agregado algo de información relacionada al entorno de pruebas Dusk; la aplicación contiene u archivo llamado .env.dusk, que define las principales configuraciones del entorno de pruebas.

De manera que, para ejecutar las pruebas Dusk, no se usá PHPUnit directamente. En su lugar, se llamara un comando artisan llamado Dusk, el cual sera un proxy a PHPUnit; esté hará un respaldo del archivo de configuración, para entonces, mover el archivo .env.dusk como archivo de configuración  para ser usado en las pruebas. Una vez terminadas las pruebas, se restaurará el archivo .env a su lugar original.

En conclusión, esta integración es una gran herramienta para las mejores practicas y calidad del software escrito utilizando Laravel.