Symfony 2.8 y TCPDF

Como obtener datos desde una base de datos y mostrarlos en un archivo pdf

Quiero explicar como hacer posible la recuperación de datos desde una tabla o conjunto de tablas relacionadas de una base de datos, accedida con Symfony 2.8 y luego transformar la información en un archivo de formato PDF usando la libreria TCPDF. También explicaré como puede diseñarse una plantilla Twig, para elegir donde ver publicados los datos: en pantalla o en un archivo pdf.

Aquí no explicaré la instalación de la librería TCPDF en Symfony2.
Un muy buen artículo acerca de como instalar y utilizar TCPDF en Symfony 2.7, puede consultarse aquí:
http://maryitsv.blogspot.com.ar/2014/11/instalacion-de-tcpdf-en-symfony-24.html

Por lo tanto, parto de suponer que Usted ya tiene instalada la librería TCPDF y desea visualizar datos de una base de datos.
Mi ejemplo, parte de tres tablas relacionadas como las que se muestran en la imagen siguiente:
tres_tablas

 

Como se deduce de la imagen, las tablas Materias y Docentes, tiene una relación de uno a muchos con la tabla Comisiones.
Supongamos que necesito hacer un listado que pueda verse en la pantalla y también que permita generar un archivo de formato PDF con los datos contenidos en estas tres tablas.
A continuación, dos capturas de pantallas de los dos resultados posibles:
En formato HTML, busco obtener este resultado:

salida_html

Y utilizando la misma plantilla Twig, quiero obtener en PDF algo como esto:

salida_pdf

Para ello, debemos primero que nada definir las rutas. Yo he creado tres rutas: comisiones_index (para ver el listado en pantalla), comisiones_indexpdf (para generar el listado y prepara la infomarción para obtener un archivo pdf) y finalmente: comisones_imprimirpdf (que procede a crear el archivo PDF y lo muestra en pantalla).

comisiones.yml
comisiones_index:
path: /
defaults: { _controller: "BackendBundle:Comisiones:index" }
methods: GET
comisiones_indexpdf:
path: /indexpdf
defaults: { _controller: "BackendBundle:Comisiones:index" }
methods: GET

A continuación, necesitamos crear los controladores. El archivo que contiene los controladores se llama: ComisionesController.php

/**
* Comisiones controller.
*
*/
class ComisionesController extends Controller
{
/**
* Lists all Comisiones entities.
*
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$comisiones = $em->getRepository('BackendBundle:Comisiones')->findComisio();

return $this->render('comisiones/index.html.twig', array(
'comisiones' => $comisiones,
));
}
public function indexpdfAction()
{
$em = $this->getDoctrine()->getManager();
$comisiones = $em->getRepository('BackendBundle:Comisiones')->findComisio();

return $this->render('comisiones/index.html.twig', array(
'comisiones' => $comisiones,
));
}

La función indexAction no requiere mayor explicación. Lo único particular que hago, es llamar a una función que me permite construir la consulta a la base de datos. Esto está contenido en la sentencia:

fragmentoLa función indexpdfAction hace lo mismo que indexAction pero la creo para poder distinguir las rutas.

La función findComisio() está en el archivo ComisionesRepository.php

El código correspondiente se muestra más abajo. Podemos observar que en la función findComisio() construyo una consulta sobre las tres tablas: Comisiones, docentes y materias.

ComisionesRepository.php

<?php
namespace BackendBundle\Entity;

use Doctrine\ORM\EntityRepository;

class ComisionesRepository extends EntityRepository

{
public function findComisio()
{
$em = $this->getEntityManager();
$consulta = $em->createQuery('
SELECT c, d, m
FROM BackendBundle:Comisiones c
JOIN c.docentes d
JOIN c.materias m
ORDER BY d.apellido, d.nombres, c.id
');
return $consulta->getArrayResult();
}

Ahora procedo a construir el archivo Twig, llamado listadocomisiones.html.twig que utilizaré tanto para ver los datos en pantalla en formato HTML como también para generar el archivo PDF con los mismos datos.
{% extends 'backend.html.twig' %}
{% block mi_cuerpo %}
{% if app.request.attributes.get('_route') == "comisiones_index" %}
{% set es_pdf = false %}
{% else %}
{% set es_pdf = true %}
{% set para_pdf = '<h1>Listado de Comisiones (ordenadas por docente y materia)</h1>' %}
{% endif %}
{% if es_pdf == true %}
{{ inicio_pdf()}}
{% endif %}
<h3>Fecha de impresión: {{ obtener_fecha() }}</h3>
{% if es_pdf == false %}

<table>
{% else %}
<table cellpadding="5" >
{% endif %}
<tr>
<td>Id</td>
<td>Nro<br>carton</td>
<td>Activa</td>
<td>Docente</td>
<td>Materia</td>
<td>Fecha<br>inicio</td>
<td>Fecha<br>final</td>
<td>Total de <br>Alum.</td>
<td>Alum. Gar.</td>
<td>Horarios</td>
<td>Intensidad</td>
<td>Turno</td>
<td>Nro<br>comision</td>
{% if es_pdf == false %}
<td>Acciones</td>
{% endif %}
</tr>
{% for comisione in comisiones %}
<tr>
<td>{{ comisione.id }}</td>
<td>{{ comisione.nroCarton }}</td>
<td>{% if comisione.activa %}Si{% else %}No{% endif %}</td>
<td>{{ comisione.docentes.apellido }}, {{ comisione.docentes.nombres }}</td>
<td>{{ comisione.materias.descripcion }}</td>
<td style="text-align:center">{% if comisione.fechaInicio %}
{{ comisione.fechaInicio|date('d/m/Y') }}{% endif %}</td>
<td style="text-align:center">{% if comisione.fechaFinal %}
{{ comisione.fechaFinal|date('d/m/Y') }}{% endif %}</td>
<td style="text-align:center">{{ comisione.totalAlumnos }}</td>
<td style="text-align:center">{{ comisione.alumnosGarantia }}</td>
<td>{{ comisione.horarios }}</td>
<td>{{ comisione.intensidad }}</td>
<td>{{ comisione.turno }}</td>
<td>{{ comisione.nroComision }}</td>
{% if es_pdf == false %}
<td>
<ul>
<li>
<a href="{{ path('comisiones_show', { 'id': comisione.id }) }}">Mostrar</a>
</li>
<li>
<a href="{{ path('comisiones_edit', { 'id': comisione.id }) }}">Editar</a>
</li>
{% if comisione.activa %}
<li>
<a href="{{ path('comisiones_liqui', { 'id': comisione.id }) }}">Liquidar</a>
</li>
{% endif %}
</ul>
</td>
{% endif %}
</tr>
{% endfor %}
</table>
{% if es_pdf == true %}
{% set hola = final_pdf(para_pdf) %}
{{ render(controller('BackendBundle:Comisiones:imprimirComisiones', {'posts' : hola })) }}
{% endif %}
{% endblock %}

La primer sentencia busca establecer desde donde se llama a la plantilla Twig. Si se llama desde la ruta comisiones_index definimos una variable es_pdf como “false” y a continuación mostramos por pantalla el título. Si el llamado a la plantilla viene de la otra ruta: comisiones_indexpdf, entonces es_pdf se define como “true”. La variable “es_pdf” me permitirá determinar las porciones del código que se muestran en HTML solamente, y cual parte del código solo se utiliza para el archivo PDF. Por supuesto, la mayor parte de la plantilla contiene código común a las dos salidas posibles: HTML o PDF.
Para el caso del archivo PDF, procedo a crear una variable llamada: para_pdf donde se guarda el título del listado. Ya veremos más adelante como concatenar el título contenido en para_pdf con el cuerpo del listado.
En este listado, utilizo tres funciones con código PHP. Como no puedo insertar en forma directa el código PHP en la plantilla Twig, debo proceder a crear las funciones en un archivo llamado AppExtension.php (Ver más abajo)

La primer función invocada en el listado Twig se llama: inicio_pdf, y me permite empezar a grabar en el buffer del navegador los datos que se van generando en la plantilla Twig. Casi al final de la plantilla Twig, se puede ver la otra función esencial para obtener el PDF: final_pdf. A esta función se le pasa como parámetro, para_pdf y luego se concatena el contenido de esta variable con el detalle del listado almacenado en el buffer, cargando todo a la variable “hola”. La tercer función que utilizo es opcional para este ejemplo. Se llama obtener_fecha y simplemente me imprime la fecha y hora actual, tanto por pantalla como en el PDF que se genere.
Obsérvese las últimas líneas de la plantilla:

listado5Allí vemos que, en caso de estar generando el archivo PDF, llamamos desde la plantilla Twig a la función imprimirComisiones a la que se le pasa la variable “hola” con todo el contenido de la plantilla Twig (ver el código detallado de la función más abajo). Esta función, que se guarda también en el archivo ComisionesController.php, simplemente construye el archivo PDF, y muestra el resultado por pantalla en formato PDF. Observese que el contenido de la variable “hola” es pasado desde la plantilla Twig al controlador. En el controlador, el contenido de “hola” ingresa como “$posts” y se imprime en el PDF que se genera.

Aquí el código:
public function imprimirComisionesAction($posts)
{
$pdf = $this->get('white_october.tcpdf')->create();
$pdf ->SetAuthor('Piero SRL');
$pdf ->SetTitle('Listado de Comisiones');
$pdf ->SetSubject('Listado');
// activa o desactiva encabezado de página
$pdf ->SetPrintHeader(false);
// activa o desactiva el pie de página
$pdf ->SetPrintFooter(true);
$pdf ->SetFont('times', '', 10);
$pdf->setPageOrientation("L");
// set default header data
$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, PDF_HEADER_TITLE.' 001',
PDF_HEADER_STRING, array(0,64,255), array(0,64,128));
$pdf->setFooterData(array(0,64,0), array(0,64,128));
// set header and footer fonts
$pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
$pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
// set default monospaced font
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
// set margins
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
// set auto page breaks
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
$pdf ->AddPage();
// escribir los datos
$pdf->writeHTMLCell(0, 0, '', '', $posts, 0, 1, 0, true, '', true );
// la siguiente línea es para limpiar el buffer de datos
ob_end_clean();
$pdf->Output('comisiones.pdf', 'I');
}
}

Dijimos que para usar funciones PHP en una plantilla Twig, debemos utilizar las extensiones de Twig. A continuación vemos la ubicación del archivo a crear:

Ubicación de AppExtension.php
appextension
Debemos también habilitar el servicio correspondiente en el archivo services.yml:
services

Finalmente debemos crear las funciones que llamamos desde Twig. El contenido de AppExtension.php puede verse a continuación:

<?php
namespace AppBundle\Twig;

class AppExtension extends \Twig_Extension
{

public function getFunctions()
{
return array(
new \Twig_SimpleFunction('inicio_pdf', array($this, 'iniciopdfFunction')),
new \Twig_SimpleFunction('final_pdf', array($this, 'finalpdfFunction')),
new \Twig_SimpleFunction('obtener_fecha', array($this, 'obtenerFecha')),
);
public function iniciopdfFunction()
{
ob_start();
return;
}

public function finalpdfFunction($para_pdf)
{
$postsbis = ob_get_contents();
$posts=$para_pdf . $postsbis;
ob_end_clean();

return $posts;
}

public function obtenerFecha()
{
setlocale(LC_ALL, "es_ES");
$timestamp=time();
$format='l j F Y H:i';

$trans = array(
'Monday' => 'Lunes,',
'Tuesday' => 'Martes,',
'Wednesday' => 'Miércoles,',
'Thursday' => 'Jueves,',
'Friday' => 'Viernes,',
'Saturday' => 'Sábado,',
'Sunday' => 'Domingo,',
'January' => ' de Enero de ',
'February' => ' de Febrero de ',
'March' => ' de Marzo de ',
'April' => ' de Abril de ',
'May' => ' de Mayo de ',
'June' => ' de Junio de ',
'July' => ' de Julio de ',
'August' => ' de Agosto de ',
'September' => ' de Septiembre de ',
'October' => ' de Octubre de ',
'November' => ' de Noviembre de ',
'December' => ' de Diciembre de ',
);
return strtr(date($format,$timestamp),$trans);
}
public function getName()
{
return 'app_extension';
}
}

Para ver en detalle como usar las extensiones de Twig, consulte el siguiente link:
http://symfony.com/doc/2.8/cookbook/templating/twig_extension.html

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s