Generación de reportes en Laravel 7 con PHPJasper (JasperReports)

domingo, junio 07, 2020
Banner Reportes

Es posible usar desde de PHP una herramienta muy poderosa para generar reportes como lo es JasperReports. Se pueden generar reportes en PDF y otros formatos.

JasperReports es una librería de creación de reportes que permite la exportación a diversos formatos tales como PDF, HTML, XLS, CSV y XML. Es una herramienta que considero bastante potente. En ésta entrada puedes ver cómo generar un reporte con esta librería.

En una entrada anterior expliqué como usar esta librería desde Laravel 5 con la instalación de un paquete llamado JasperPHP que permite generar reportes con el uso de JasperReports a través de la herramienta de linea de comandos JasperStarter.

Bajo el mismo concepto hoy traigo un tutorial para Laravel 7, en este caso usando un paquete similar pero más actualizado a la fecha de hoy llamado PHPJasper.

Ambos paquetes mencionados pueden usarse para generar reportes desde cualquier proyecto en PHP (>=7), de igual manera que en Laravel.


Instalación de Laravel 7

Para el tutorial, he descargado la versión 7.14.1 de Laravel siguiendo las indicaciones de su documentación oficial.

Para la instalación del Laravel y del paquete que vamos usar requerimos tener instalado Composer.


Requerimientos mínimos para Instalar PHPJasper


Instalación de PHPJasper en Laravel 7

Ingresar en el proyecto desde la línea de comandos y ejecutar el siguiente comando:

composer require geekcom/phpjasper

Luego actualizamos para que se descargue:

composer update

¡Y listo! Con eso lo tendrás instalado el paquete.


Uso de PHPJasper en Laravel 7

Si nunca han usado JasperReports pueden ver ésta entrada donde les muestro como crear un reporte en JasperReports desde cero. Les recomiendo Jaspersoft Studio para tal fin. En esta entrada para demostrar el uso de PHPJasper vamos a utilizar los reportes de ejemplo hello_world.jrxml y hello_world_params.jrxml que vienen con el paquete y se encuentran en la ruta vendor/geekcom/phpjasper/examples/.

Inicialmente tienes que añadir la librería donde la vas a usar (para este ejemplo en routes/web.php):

use PHPJasper\PHPJasper; 

La clase PHPJasper nos provee un método para compilar los reportes llamado compile() y se usa de la siguiente manera (no es necesario este paso si lo hace antes desde un programa como Jaspersoft Studio):

Route::get('/compilarReporte', function () {
    $input = base_path() .
    '/vendor/geekcom/phpjasper/examples/hello_world.jrxml';

    $jasper = new PHPJasper;
    $jasper->compile($input)->execute();

    return response()->json([
        'status' => 'ok',
        'msj' => '¡Reporte compilado!'
    ]);
});

Si todo sale bien al ingresar desde el navegador a la ruta del proyecto /compilarReporte debe recibir un json como respuesta:

{
  "status": "ok",
  "msj": "¡Reporte compilado!"
}

Esto va a crear un nuevo archivo en la ruta vendor/geekcom/phpjasper/examples. Una vez que tengas el archivo .jasper generado puedes ejecutar el reporte desde la ruta /reporte:

Route::get('/reporte', function () {
    $input = base_path() .
    '/vendor/geekcom/phpjasper/examples/hello_world.jasper';
    $output = base_path() .
    '/vendor/geekcom/phpjasper/examples';
    $options = [
        'format' => ['pdf']
    ];

    $jasper = new PHPJasper;

    $jasper->process(
        $input,
        $output,
        $options
    )->execute();

    $pathToFile = base_path() .
    '/vendor/geekcom/phpjasper/examples/hello_world.pdf';
    return response()->file($pathToFile);
});

Se debe ver en el navegador el resultado:

Otra de las posibilidades que nos da el paquete es enviar parámetros al reporte, para listar los parámetros que requiere el reporte vamos a usar lo siguiente:

Route::get('/listarParametrosReporte', function () {
    $input = base_path() .
    '/vendor/geekcom/phpjasper/examples/hello_world_params.jrxml';

    $jasper = new PHPJasper;
    $output = $jasper->listParameters($input)->execute();

    return response()->json([
        'status' => 'ok',
        'parms' => $output
    ]);
});

Si entramos a la ruta /listarParametrosReporte vamos obtener algo como esto:

{
  "status": "ok",
  "parms": [
    "P myString java.lang.String",
    "P myInt    java.lang.Integer",
    "P myDate   java.util.Date",
    "P myImage  java.awt.Image    This is the description of parameter myImage"
  ]
}

Luego de manera similar al primer ejemplo vamos a crear una ruta para compilar el reporte con parámetros:

Route::get('/compilarReporteParametros', function () {
    $input = base_path() .
    '/vendor/geekcom/phpjasper/examples/hello_world_params.jrxml';

    $jasper = new PHPJasper;
    $jasper->compile($input)->execute();

    return response()->json([
        'status' => 'ok',
        'msj' => '¡Reporte compilado!'
    ]);
});

Si todo sale bien al ingresar desde el navegador a la ruta del proyecto /compilarReporteParametros debe recibir un json como respuesta:

{
  "status": "ok",
  "msj": "¡Reporte compilado!"
}

Para ejecutar el reporte con parámetros necesitamos una imagen en el directorio vendor/geekcom/phpjasper/examples/ en este caso estoy usando el siguiente logo de JasperReports:

Luego defino una ruta para ejecutar el reporte con parámetros como sigue:

Route::get('/reporteParametros', function () {
    $input = base_path() .
    '/vendor/geekcom/phpjasper/examples/hello_world_params.jasper';
    $output = base_path() .
    '/vendor/geekcom/phpjasper/examples';
    $options = [
        'format' => ['pdf'],
        'params' => [
            'myInt' => 7,
            'myDate' => date('y-m-d'),
            'myImage' => base_path() .
            '/vendor/geekcom/phpjasper/examples/jasperreports_logo.png',
            'myString' => 'Hola Mundo!'
        ]
    ];

    $jasper = new PHPJasper;

    $jasper->process(
        $input,
        $output,
        $options
    )->execute();

    $pathToFile = base_path() .
    '/vendor/geekcom/phpjasper/examples/hello_world_params.pdf';
    return response()->file($pathToFile);
});

El resultado será el como sigue:



Depuración de errores con PHPJasper

Luego de seguir todos los pasos al pie de la letra puede ser que veas el siguiente error:

Fatal error: Uncaught PHPJasper\Exception\ErrorCommandExecutable: Your report has an error and couldn 't be processed!\ Try to output the command using the function `output();` and run it manually in the console.


La clase PHPJasper nos provee una función llamada output() que nos retorna el comando que se esta tratando de ejecutar al generar el reporte. Para poder depurar este comando directamente desde el código lo puedes hacer reemplazando el comando execute con output:

    // Depuración de errores
    dd($jasper->process(
        $input,
        $output,
        $options
    )->output());

De esta manera podrás visualizar el comando que se trata de ejecutar. Solo es cuestión de copiarlo en la consola y ver el verdadero error que te ocurre.


Errores frecuentes con PHPJasper

  • Falta de permisos de escritura en la ruta vendor/geekcom/phpjasper/examples/.
  • El reporte de ejemplo usa la fuente Arial, es posible que si está en linux veas el siguiente error:

    net.sf.jasperreports.engine.util.JRFontNotFoundException: Font 'Arial' is not available to the JVM. See the Javadoc for more details. at net.sf.jasperreports.engine.util.JRFontUtil.checkAwtFont(JRFontUtil.java:321) at net.sf.jasperreports.engine.util.JRStyledText.getAwtAttributedString(JRStyledText.java:226)

    La solución detallada la encuentras aquí:
    sudo apt-get install ttf-mscorefonts-installer
    sudo cp -r /usr/share/fonts/truetype/msttcorefonts $JAVA_HOME/lib/fonts
        

Espero que sea de utilidad. Cualquier duda o aporte te invito a que la dejes en los comentarios :).

También te puede interesar

Cuando navego por los sitios web, mi parte favorita es leer los comentarios. Es por eso que tus comentarios son un complemento valioso para mis entradas. Cualquier duda o aporte no dejes de escribirlo, en breve lo estaré publicando. ¡Gracias!


2 comentarios

Lo más reciente

¡Bendiciones para mi Venezuela!

¡Bendiciones para mi Venezuela!