Instalando y utilizando Debugbar en Lumen

Publicado por Alejandro Escario en

Existen multitud de proyectos para ayudar en las tareas de debug y mantenimiento de proyectos basados en Laravel. Sin embargo, el número de proyectos dedicados a esta tarea disminuye drásticamente cuando queremos desarrollar un proyecto en Lumen.

Lumen tiene una gran cantidad de ventajas con respecto a su hermano mayor si vamos a definir una API. Pero entre las desventajas que tiene es que no siempre se encuentra tanta documentación ni librerías adaptadas.

En este artículo vamos a describir paso a paso cómo crear un proyecto basado en Lumen 8, instalar el plugin de debugbar y configurarlo sin romper la API.

Creación del proyecto

El primer paso es crear el proyecto Lumen. Si ya tienes un proyecto sobre el que desees usar el paquete, puedes pasar al siguiente punto.

~$ composer create-project --prefer-dist laravel/lumen debugbar_lumen                                                  
Creating a "laravel/lumen" project at "./debugbar_lumen"
Installing laravel/lumen (v8.1.1)
- Installing laravel/lumen (v8.1.1): Extracting archive
Created project in ./20210712 Debugbar laravel/debugbar_lumen
> @php -r "file_exists('.env') || copy('.env.example', '.env');"
Loading composer repositories with package information
Updating dependencies
Lock file operations: 106 installs, 0 updates, 0 removals
- Locking brick/math (0.9.2)
- Locking doctrine/inflector (2.0.3)
- Locking doctrine/instantiator (1.4.0)
- Locking doctrine/lexer (1.2.1)
- Locking dragonmantank/cron-expression (v3.1.0)
- Locking egulias/email-validator (2.1.25)
- Locking fakerphp/faker (v1.15.0)
- Locking graham-campbell/result-type (v1.0.1)
- Locking hamcrest/hamcrest-php (v2.0.1)
- Locking illuminate/auth (v8.49.2)
- Locking illuminate/broadcasting (v8.49.2)
- Locking illuminate/bus (v8.49.2)
- Locking illuminate/cache (v8.49.2)
- Locking illuminate/collections (v8.49.2)
- Locking illuminate/config (v8.49.2)
- Locking illuminate/console (v8.49.2)
- Locking illuminate/container (v8.49.2)
- Locking illuminate/contracts (v8.49.2)
- Locking illuminate/database (v8.49.2)
- Locking illuminate/encryption (v8.49.2)
- Locking illuminate/events (v8.49.2)
- Locking illuminate/filesystem (v8.49.2)
- Locking illuminate/hashing (v8.49.2)
- Locking illuminate/http (v8.49.2)
- Locking illuminate/log (v8.49.2)
- Locking illuminate/macroable (v8.49.2)
- Locking illuminate/pagination (v8.49.2)
- Locking illuminate/pipeline (v8.49.2)
- Locking illuminate/queue (v8.49.2)
- Locking illuminate/session (v8.49.2)
- Locking illuminate/support (v8.49.2)
- Locking illuminate/testing (v8.49.2)
- Locking illuminate/translation (v8.49.2)
- Locking illuminate/validation (v8.49.2)
- Locking illuminate/view (v8.49.2)
- Locking laravel/lumen-framework (v8.2.4)
- Locking mockery/mockery (1.4.3)
- Locking monolog/monolog (2.3.0)
- Locking myclabs/deep-copy (1.10.2)
- Locking nesbot/carbon (2.50.0)
- Locking nikic/fast-route (v1.3.0)
- Locking nikic/php-parser (v4.11.0)
- Locking opis/closure (3.6.2)
- Locking phar-io/manifest (2.0.1)
- Locking phar-io/version (3.1.0)
- Locking phpdocumentor/reflection-common (2.2.0)
- Locking phpdocumentor/reflection-docblock (5.2.2)
- Locking phpdocumentor/type-resolver (1.4.0)
- Locking phpoption/phpoption (1.7.5)
- Locking phpspec/prophecy (1.13.0)
- Locking phpunit/php-code-coverage (9.2.6)
- Locking phpunit/php-file-iterator (3.0.5)
- Locking phpunit/php-invoker (3.1.1)
- Locking phpunit/php-text-template (2.0.4)
- Locking phpunit/php-timer (5.0.3)
- Locking phpunit/phpunit (9.5.6)
- Locking psr/container (1.1.1)
- Locking psr/event-dispatcher (1.0.0)
- Locking psr/log (1.1.4)
- Locking psr/simple-cache (1.0.1)
- Locking ramsey/collection (1.1.3)
- Locking ramsey/uuid (4.1.1)
- Locking sebastian/cli-parser (1.0.1)
- Locking sebastian/code-unit (1.0.8)
- Locking sebastian/code-unit-reverse-lookup (2.0.3)
- Locking sebastian/comparator (4.0.6)
- Locking sebastian/complexity (2.0.2)
- Locking sebastian/diff (4.0.4)
- Locking sebastian/environment (5.1.3)
- Locking sebastian/exporter (4.0.3)
- Locking sebastian/global-state (5.0.3)
- Locking sebastian/lines-of-code (1.0.3)
- Locking sebastian/object-enumerator (4.0.4)
- Locking sebastian/object-reflector (2.0.4)
- Locking sebastian/recursion-context (4.0.4)
- Locking sebastian/resource-operations (3.0.3)
- Locking sebastian/type (2.3.4)
- Locking sebastian/version (3.0.2)
- Locking symfony/console (v5.3.2)
- Locking symfony/deprecation-contracts (v2.4.0)
- Locking symfony/error-handler (v5.3.3)
- Locking symfony/event-dispatcher (v5.3.0)
- Locking symfony/event-dispatcher-contracts (v2.4.0)
- Locking symfony/finder (v5.3.0)
- Locking symfony/http-client-contracts (v2.4.0)
- Locking symfony/http-foundation (v5.3.3)
- Locking symfony/http-kernel (v5.3.3)
- Locking symfony/mime (v5.3.2)
- Locking symfony/polyfill-ctype (v1.23.0)
- Locking symfony/polyfill-intl-grapheme (v1.23.0)
- Locking symfony/polyfill-intl-idn (v1.23.0)
- Locking symfony/polyfill-intl-normalizer (v1.23.0)
- Locking symfony/polyfill-mbstring (v1.23.0)
- Locking symfony/polyfill-php72 (v1.23.0)
- Locking symfony/polyfill-php73 (v1.23.0)
- Locking symfony/polyfill-php80 (v1.23.0)
- Locking symfony/process (v5.3.2)
- Locking symfony/service-contracts (v2.4.0)
- Locking symfony/string (v5.3.3)
- Locking symfony/translation (v5.3.3)
- Locking symfony/translation-contracts (v2.4.0)
- Locking symfony/var-dumper (v5.3.3)
- Locking theseer/tokenizer (1.2.0)
- Locking vlucas/phpdotenv (v5.3.0)
- Locking voku/portable-ascii (1.5.6)
- Locking webmozart/assert (1.10.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 106 installs, 0 updates, 0 removals
- Installing doctrine/inflector (2.0.3): Extracting archive
- Installing symfony/polyfill-php72 (v1.23.0): Extracting archive
- Installing symfony/polyfill-intl-normalizer (v1.23.0): Extracting archive
- Installing symfony/polyfill-intl-idn (v1.23.0): Extracting archive
- Installing doctrine/lexer (1.2.1): Extracting archive
- Installing egulias/email-validator (2.1.25): Extracting archive
- Installing symfony/deprecation-contracts (v2.4.0): Extracting archive
- Installing psr/container (1.1.1): Extracting archive
- Installing fakerphp/faker (v1.15.0): Extracting archive
- Installing symfony/polyfill-php80 (v1.23.0): Extracting archive
- Installing symfony/polyfill-mbstring (v1.23.0): Extracting archive
- Installing symfony/http-foundation (v5.3.3): Extracting archive
- Installing symfony/finder (v5.3.0): Extracting archive
- Installing voku/portable-ascii (1.5.6): Extracting archive
- Installing symfony/translation-contracts (v2.4.0): Extracting archive
- Installing symfony/translation (v5.3.3): Extracting archive
- Installing nesbot/carbon (2.50.0): Extracting archive
- Installing illuminate/macroable (v8.49.2): Extracting archive
- Installing psr/simple-cache (1.0.1): Extracting archive
- Installing illuminate/contracts (v8.49.2): Extracting archive
- Installing illuminate/collections (v8.49.2): Extracting archive
- Installing illuminate/support (v8.49.2): Extracting archive
- Installing illuminate/filesystem (v8.49.2): Extracting archive
- Installing illuminate/session (v8.49.2): Extracting archive
- Installing symfony/polyfill-ctype (v1.23.0): Extracting archive
- Installing phpoption/phpoption (1.7.5): Extracting archive
- Installing graham-campbell/result-type (v1.0.1): Extracting archive
- Installing vlucas/phpdotenv (v5.3.0): Extracting archive
- Installing symfony/var-dumper (v5.3.3): Extracting archive
- Installing symfony/mime (v5.3.2): Extracting archive
- Installing symfony/polyfill-php73 (v1.23.0): Extracting archive
- Installing symfony/http-client-contracts (v2.4.0): Extracting archive
- Installing psr/event-dispatcher (1.0.0): Extracting archive
- Installing symfony/event-dispatcher-contracts (v2.4.0): Extracting archive
- Installing symfony/event-dispatcher (v5.3.0): Extracting archive
- Installing psr/log (1.1.4): Extracting archive
- Installing symfony/error-handler (v5.3.3): Extracting archive
- Installing symfony/http-kernel (v5.3.3): Extracting archive
- Installing symfony/polyfill-intl-grapheme (v1.23.0): Extracting archive
- Installing symfony/string (v5.3.3): Extracting archive
- Installing symfony/service-contracts (v2.4.0): Extracting archive
- Installing symfony/console (v5.3.2): Extracting archive
- Installing nikic/fast-route (v1.3.0): Extracting archive
- Installing illuminate/container (v8.49.2): Extracting archive
- Installing illuminate/pipeline (v8.49.2): Extracting archive
- Installing illuminate/bus (v8.49.2): Extracting archive
- Installing illuminate/events (v8.49.2): Extracting archive
- Installing illuminate/view (v8.49.2): Extracting archive
- Installing illuminate/translation (v8.49.2): Extracting archive
- Installing illuminate/validation (v8.49.2): Extracting archive
- Installing illuminate/testing (v8.49.2): Extracting archive
- Installing symfony/process (v5.3.2): Extracting archive
- Installing ramsey/collection (1.1.3): Extracting archive
- Installing brick/math (0.9.2): Extracting archive
- Installing ramsey/uuid (4.1.1): Extracting archive
- Installing opis/closure (3.6.2): Extracting archive
- Installing illuminate/database (v8.49.2): Extracting archive
- Installing illuminate/console (v8.49.2): Extracting archive
- Installing illuminate/queue (v8.49.2): Extracting archive
- Installing illuminate/pagination (v8.49.2): Extracting archive
- Installing monolog/monolog (2.3.0): Extracting archive
- Installing illuminate/log (v8.49.2): Extracting archive
- Installing illuminate/http (v8.49.2): Extracting archive
- Installing illuminate/hashing (v8.49.2): Extracting archive
- Installing illuminate/encryption (v8.49.2): Extracting archive
- Installing illuminate/config (v8.49.2): Extracting archive
- Installing illuminate/cache (v8.49.2): Extracting archive
- Installing illuminate/broadcasting (v8.49.2): Extracting archive
- Installing illuminate/auth (v8.49.2): Extracting archive
- Installing webmozart/assert (1.10.0): Extracting archive
- Installing dragonmantank/cron-expression (v3.1.0): Extracting archive
- Installing laravel/lumen-framework (v8.2.4): Extracting archive
- Installing hamcrest/hamcrest-php (v2.0.1): Extracting archive
- Installing mockery/mockery (1.4.3): Extracting archive
- Installing phpdocumentor/reflection-common (2.2.0): Extracting archive
- Installing phpdocumentor/type-resolver (1.4.0): Extracting archive
- Installing phpdocumentor/reflection-docblock (5.2.2): Extracting archive
- Installing sebastian/version (3.0.2): Extracting archive
- Installing sebastian/type (2.3.4): Extracting archive
- Installing sebastian/resource-operations (3.0.3): Extracting archive
- Installing sebastian/recursion-context (4.0.4): Extracting archive
- Installing sebastian/object-reflector (2.0.4): Extracting archive
- Installing sebastian/object-enumerator (4.0.4): Extracting archive
- Installing sebastian/global-state (5.0.3): Extracting archive
- Installing sebastian/exporter (4.0.3): Extracting archive
- Installing sebastian/environment (5.1.3): Extracting archive
- Installing sebastian/diff (4.0.4): Extracting archive
- Installing sebastian/comparator (4.0.6): Extracting archive
- Installing sebastian/code-unit (1.0.8): Extracting archive
- Installing sebastian/cli-parser (1.0.1): Extracting archive
- Installing phpunit/php-timer (5.0.3): Extracting archive
- Installing phpunit/php-text-template (2.0.4): Extracting archive
- Installing phpunit/php-invoker (3.1.1): Extracting archive
- Installing phpunit/php-file-iterator (3.0.5): Extracting archive
- Installing theseer/tokenizer (1.2.0): Extracting archive
- Installing nikic/php-parser (v4.11.0): Extracting archive
- Installing sebastian/lines-of-code (1.0.3): Extracting archive
- Installing sebastian/complexity (2.0.2): Extracting archive
- Installing sebastian/code-unit-reverse-lookup (2.0.3): Extracting archive
- Installing phpunit/php-code-coverage (9.2.6): Extracting archive
- Installing doctrine/instantiator (1.4.0): Extracting archive
- Installing phpspec/prophecy (1.13.0): Extracting archive
- Installing phar-io/version (3.1.0): Extracting archive
- Installing phar-io/manifest (2.0.1): Extracting archive
- Installing myclabs/deep-copy (1.10.2): Extracting archive
- Installing phpunit/phpunit (9.5.6): Extracting archive
46 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating optimized autoload files
62 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

Ua vez tenemos instalado correctamente Lumen, vamos a comprobar que el proyecto se ha generado correctamente:

~$ cd debugbar_lumen      
~$ php -S localhost:8000 -t public                                                                            
PHP 7.3.27 Development Server started at Mon Jul 12 22:36:12 2021
Listening on http://localhost:8000
Document root is /.../debugbar_lumen/public
Press Ctrl-C to quit.

Instalación de la barra de debug

Usando Composer instalamos la dependencia de DebugBar

~$ composer require barryvdh/laravel-debugbar --dev                                                           
Using version ^3.6 for barryvdh/laravel-debugbar
./composer.json has been updated
Running composer update barryvdh/laravel-debugbar
Loading composer repositories with package information
Updating dependencies
Lock file operations: 5 installs, 0 updates, 0 removals
- Locking barryvdh/laravel-debugbar (v3.6.2)
- Locking illuminate/routing (v8.49.2)
- Locking maximebf/debugbar (v1.16.5)
- Locking symfony/debug (v4.4.25)
- Locking symfony/routing (v5.3.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 5 installs, 0 updates, 0 removals
- Installing symfony/debug (v4.4.25): Extracting archive
- Installing maximebf/debugbar (v1.16.5): Extracting archive
- Installing symfony/routing (v5.3.0): Extracting archive
- Installing illuminate/routing (v8.49.2): Extracting archive
- Installing barryvdh/laravel-debugbar (v3.6.2): Extracting archive
7 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating optimized autoload files
65 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

Ahora tenemos por objetivo poder indicar cuándo queremos que se muestren los datos del Debugbar en nuestra API. Para ello modificaremos el fichero .env y el fichero .env.example (para que si alguien más instala nuestra aplicación tenga una referencia) y pondremos la variable APP_DEBUG a true y una nueva variable llamada DEBUGBAR_ENABLED que permitirá habilitar y deshabilitar la barra de debug. La barra de debug se mostrará únicamente cuando este valor sea verdadero.

Abrimos el fichero bootstrap/app.php y habilitamos, si APP_DEBUG=true y la petición no se está ejecutando desde consola la inyección del provider:

if (!$app->runningInConsole() && config('APP_DEBUG')) {
$app->register(Barryvdh\Debugbar\LumenServiceProvider::class);
}

Esta comprobación de que ejecutamos desde consola nos permite bypasear determinados errores que puede dar debugbar en Lumen, como:

Argument 2 passed to Barryvdh\Debugbar\ServiceProvider::Barryvdh\Debugbar\{closure}() must be an instance of Illuminate\Foundation\Application, instance of Laravel\Lumen\Application given, called in ./vendor/illuminate/container/Container.php on line 763 {«exception»:»[object] (TypeError(code: 0): Argument 2 passed to Barryvdh\\Debugbar\\ServiceProvider::Barryvdh\\Debugbar\\{closure}() must be an instance of Illuminate\\Foundation\\Application, instance of Laravel\\Lumen\\Application given, called in ./vendor/illuminate/container/Container.php on line 763 at ./vendor/barryvdh/laravel-debugbar/src/ServiceProvider.php:59)

Finalmente copiaremos el fichero de configuración en la carpeta config:

~$ mkdir config                                                                                               
~$ cp vendor/barryvdh/laravel-debugbar/config/debugbar.php config

Y, de nuevo, en el fichero bootstrap/app.php, realizaremos un cambio para activar este fichero de configuración. Para ello añadiremos la siguiente línea:

$app->configure('debugbar');

Ha llegado el momento de comprobar que no hemos cometido ningún error. Para ello vamos a volver a levantar el servidor:

~$ php -S localhost:8000 -t public                                                                            
PHP 7.3.27 Development Server started at Mon Jul 12 22:36:12 2021
Listening on http://localhost:8000
Document root is /.../debugbar_lumen/public
Press Ctrl-C to quit.

Y con curl o con un programa similar a Postman vamos a realizar una petición al servidor:

Petición básica desde POSTMAN a la API

El problema es que estamos definiendo una API y queremos que devuelva, en este caso, los datos en JSON. Por ello vamos a hacer un pequeño cambio en el fichero routes/web.php, convirtiendo:

$router->get('/', function () use ($router) {
return $router->app->version();
});

en

$router->get('/', function () use ($router) {
return response()->json(['version' => $router->app->version()]);
});

De este modo, repitiendo la misma llamada que antes, obtendremos el siguiente valor por respuesta:

Obtención de la versión en json

Si ahora habilitásemos la Debugbar, estaríamos generando una respuesta JSON inválida, así que vamos a incluir el resultado en json de respuesta. Para ello vamos a crear el fichero app/Http/Middleware/JsonDebugbar.php con el siguiente código extraído de un ticket cerrado del propio proyecto:

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\JsonResponse;
class JsonDebugbar
{
/**
* Handle an incoming request.
*
* @param  \Illuminate\Http\Request  $request
* @param  \Closure  $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
if (
$response instanceof JsonResponse &&
app()->bound('debugbar') &&
app('debugbar')->isEnabled() &&
is_object($response->getData())
) {
$response->setData($response->getData(true) + [
'_debugbar' => app('debugbar')->getData(),
]);
}
return $response;
}
}

a) Añadir al fichero de rutas el middleware

Vamos a registrar el nuevo middleware a nivel de ruta. Para hacer esto tenemos dos opciones: en el fichero bootstrap/app.php añadiendo la siguiente línea:

$app->routeMiddleware([
'jsonDebugbar' => App\Http\Middleware\JsonDebugbar::class,
// more middlewares to be declared
]);

Si ahora realizamos otra petición a través de postman, veremos que aun no se aplican los cambios, porque la ruta en cuestión necesita invocar al middleware.

Para hacer esto modificaremos el fichero routes/web.php e introduciremos el grupo que invoque al middleware:

$router->group(['middleware' => 'jsonDebugbar'], function () use ($router) {
$router->get('/', function () use ($router) {
return response()->json(['version' => $router->app->version()]);
});
});

b) Añadir a nivel global el middleware

Para ello modificaremos el fichero bootstrap/app.php y añadiremos el middleware:

$app->middleware([
App\Http\Middleware\JsonDebugbar::class
]);

Comprobaciones

Si una vez invocado el middleware realizamos una petición a través de postman, podremos observar como somos capaces de ver el detalle de la petición con:

  • Tiempos
  • Modelos
  • Queries
  • etc.
Petición postman con el elemento del debugbar.
Categorías: Tutoriales

0 comentarios

Deja una respuesta

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *