Crear archivos PDF con CakePHP
- enero 23, 2010
- 38 comentario/s
- CakePHP Tags: tutoriales
En este post voy a comentar lo que he hecho para crear archivos PDF con CakePHP.
Los ingredientes para esta “receta” son:
1.- La librería TCPDF que se encarga de generar los archivos PDF.
2.- Un layout
3.- Una vista
Para implementar esta funcionalidad en vuestro desarrollo en CakePHP es muy sencillo y da muy buenos resultados.
- Tendréis que descargar la última versión de la librería TCPDF que como he dicho es la encargada de generar los documentos PDF.
- Tendréis que crear la carpeta app/vendors/tcpdf y extraer los ficheros en esta ruta. Al menos necesitareis copiar el archivo tcpdf.php y las carpetas tcpdf/config y tcpdf/fonts.
Por defecto la librería TCPDF crea unas cabeceras y pie definidas en los métodos header() y footer(), lo que hacemos es sobrescribir estos métodos creando una clase en app/vendors/tcpdf que extienda las propiedades y métodos de la librería TCPDF. Para ello creamos el archivo app/vendors/tcpdf/xtcpdf.php
<?php
App::import('Vendor','tcpdf/tcpdf');
class XTCPDF extends TCPDF
{
var $xheadertext = 'PDF creado using CakePHP y TCPDF';
var $xheadercolor = array(0,0,200);
var $xfootertext = 'Copyright © %d XXXXXXXXXXX. All rights reserved.';
var $xfooterfont = PDF_FONT_NAME_MAIN ;
var $xfooterfontsize = 8 ;
function Header()
{
list($r, $b, $g) = $this->xheadercolor;
$this->setY(10);
$this->SetFillColor($r, $b, $g);
$this->SetTextColor(0 , 0, 0);
$this->Cell(0,20, '', 0,1,'C', 1);
$this->Text(15,26,$this->xheadertext );
}
function Footer()
{
$year = date('Y');
$footertext = sprintf($this->xfootertext, $year);
$this->SetY(-20);
$this->SetTextColor(0, 0, 0);
$this->SetFont($this->xfooterfont,'',$this->xfooterfontsize);
$this->Cell(0,8, $footertext,'T',1,'C');
}
}
?>
Por supuesto se puede modificar el valor de las variables para customizarlas a vuestro modo. Hay muchos mas parametros y variables que se pueden añadir y customizar en la documentación de TCPDF.
<?php
header("Content-type: application/pdf");
echo $content_for_layout;
?>
function descargar($id = null)
{
if (!$id)
{
$this->Session->setFlash('no has seleccionado ningun pdf.');
$this->redirect(array('action'=>'index'));
}
// Sobrescribimos para que no aparezcan los resultados de debuggin
// ya que sino daria un error al generar el pdf.
Configure::write('debug',0);
$resultado = $this->MiControlador->findById($id);
$this->set("datos_pdf",$resultado);
$this->layout = 'pdf'; //esto usara el layout pdf.ctp
$this->render();
}
Esta función es de ejemplo, podreis desarrollar la lógica que necesitéis para obtener la información. Pero lo realmente importante es la renderizacion de los datos en el nuevo layout.
$this->layout = 'pdf'; $this->render();
<?php
App::import('Vendor','xtcpdf');
$tcpdf = new XTCPDF();
$textfont = 'freesans';
$tcpdf->SetAuthor("");
$tcpdf->SetAutoPageBreak( false );
$tcpdf->setHeaderFont(array($textfont,'',10));
$tcpdf->xheadercolor = array(255,255,255);
$tcpdf->xheadertext = 'Fecha: '. date('d-m-Y',time());
$tcpdf->xfootertext = 'www.pedroventura.com';
// Ahora imprimimos el contenido de la pagina en una posición determinada
// estos datos son un ejemplo, y en mi ejemplo hay un pequeño texto y una imagen.
$tcpdf->AddPage();
$tcpdf->SetTextColor(0, 0, 0);
$tcpdf->SetFont($textfont,'B',10);
$tcpdf->Cell(10,20,'Nombre:', 0, 0);
// configuramos la calidad de JPEG
$tcpdf->setJPEGQuality(100);
$tcpdf->Image($imagen, 0, 50, 200, 200, '', '', '', false, 150);
// se pueden asignar mas datos, ver la documentación de TCPDF
echo $tcpdf->Output('mi_archivo.pdf', 'I'); //el pdf se muestra en el navegador
//echo $tcpdf->Output('mi_archivo.pdf', 'I'); //el pdf se descarga
?>
en el segundo parámetro del Output yo tengo ‘I’, esto es que el PDF se generará en una nueva ventana del navegador. Si ponemos el parámetro: ‘D’ el pdf generado se descargará.
fuente: http://bakery.cakephp.org/articles/view/creating-pdf-files-with-cakephp-and-tcpdf
Tags de búsquedas:
cakephp pdf, pdf cakephp, cakephp en pdf, tcpdf error: some data has already been output to browser cant send pdf file, propiedad ouput del tcpdf, error tcpdf no se puede mostrar imagen, decragar TCPDF libreria para linux, como mostrar registros de db con la clase tcpdf, COLOCAR HORA EN TCPDF, tcpdf media print
Posts Relacionados:
- componente geo posicionamiento ip con cakephp Con este componente podrás geo posicionar algunas secciones de tu web, mediante una base de datos con los países. Se puede Geoposiciar un site entero pero no es nada recomendable...
- Cakephp generar logs con $this->log(); Generar logs de datos en CakePHP es muy simple y útil con la función log() que es parte de la clase Object que es común para la mayoria de las...
- CakePHP Helper para crear un listado de países Necesitaba para mi registro una manera de integrar el típico select option con los nombres de los países. He creado un Helper para CakePHP que genera un listado de los...
- Captcha de seguridad en cakePHP con Securimage Lo primero algo de teoría.. ¿Qué es Securimage? Securimage es un código abierto libre script PHP CAPTCHA para la generación de imágenes complejas y códigos CAPTCHA para proteger las formas...
- problema en CacheHelper, crea archivos de caché que pueden entrar en conflicto Hay un problema bastante serio tanto con el helper de Cache de cakephp como en algunos elementos del core de éste framework, en este caso mas en concreto con el...

Te ha ayudado el artículo? Colabora!
RSS Feed
Lamentablemente no me funciona. Me sale el siguiente error:
TCPDF ERROR: Some data has already been output, can’t send PDF file
No se cómo solucionarlo. ¿Alguien me ayuda?
Buenos dias, felicitaciones por tu blogs y los diferentes notas contenida en ella, una pregunta a ver como me puede ayudar:
Tengo un reporte en TCPDF, en donde la primera hoja quiero imprimir una cabezera y a partir de la segunda en adelenate otra, trato de hacerla de esta manera:
public function Header($segundaHoja,$banco,$cliente,$Cta_cte,$fecha_finals,$ano) {
if ($segundaHoja===true) {
// *** replace the following parent::Header() with your code for TOC page
//parent::Header();
$this->Image(‘/var/www/SISCONVAPOST/app/webroot/img/LogoUnerg.jpg’,10,10,40,20);
$this->Cell(180,3,”Respublica Bolivariana de Venzuela”,0,1,’C');
$this->Cell(180,4,”Universidad Rómulo Gallegos”,0,1,’C');
$this->Cell(180,5,”San Juan de los Morros Ed. Guárico”,0,1,’C');
} else {
// *** replace the following parent::Header() with your code for normal pages
//parent::Header();
//$this->SetX(10);
$this->Cell(180,6,$banco,0,1,’C');
$this->Cell(180,7,$cliente,0,1,’C');
$this->Cell(180,8,”Cta. Cte. Nº.: “.$Cta_cte,0,1,’C');
$this->Cell(180,7,”Depositos Originales Correspondiente al mes “.$fecha_finals.” de “.$ano,0,1,’C');
}
Pero no sale, como quiero, a partir de la 3 hojas no sale ningun encabezado, sera q me podrias orientar. gracias
Felicitaciones por tu blog. Relamente tienes una forma de explicar las cosas y una dedicacion digna de destacar. Muchas gracias por tu tiempo y tu generosidad.
hola pedro,hice tu ejemplo para mi tabla cotizaciones que quiero exportar a pdf
y aparece
Error del servidor
El sitio web ha detectado un error al recuperar la Es posible que esta esté inactiva debido a tareas de mantenimiento o que se haya configurado de forma incorrecta.
cambio el debug a 3 y aparece:
Fatal error: Class ‘XTCPDF’ not found in
ojala puedas ayudarme
gracias por tu rapida respuesta como ayudas con tu blog ¬¬
Hola despues de buscar mucho encontre tu tutorial, y esta genial!!! muchas gracias me funciona a la perfeccion, pero tengo un pequeño problema, como hago para que en el documento me muestre mas de una tupla de la base de datos?, por ejemplo como sacar un reporte de todos los usuarios que nacieron en 1990… Gracias de antemano…
Pues esto es tema de mysql. Tendrá que mirarte la documentación de mysql, pero será algo similar a esto:
Mil gracias por responder… ya solucione ese tema y ya muestro los datos de mi bd con querys a la misma… todo bien!!! hasta ahi… , es decir localmente funciona a mil maravillas hasta redimencione el tamaño de la hoja 1/2 carta para que me imprima notas de entrega, recibos, etc., pero cuando subí la pagina al servidor y probe, me sale el siguiente error:
TCPDF ERROR: Some data has already been output to browser, can’t send PDF file
No me muestra los pdf como cuando funciona localmente…
Te agradeceria alguna sugerencia para solucionar aquello, ya revise lo de los espacios antes y despues de ….
Gracias de antemano…
Puede que sea que en local tienes algún reporte de errores y en producción no. Prueba a poner al principio del php
Sino, esto me ha pasado a veces que hay algún espacio en blanco en el fichero, normalmente al final de éste y da este problema
Wooow gracias por este tuto, es el mejor que encontre de verdad me sirvio mucho funciona a la perfeccion
Muy bueno el tuto, yo había probado con dompdf pero me daba algunos errores al rederizar la vista, pero con tcpdf me esta funcionando de maravilla aunque sea mas moroso crear el pdf.
Primero que nada: Gracias por este articulo tan útil! segui las instrucciones y logre ver el archivo pdf (aunque no se mostró la imagen pero si el texto). Ahora quiero visualizar los datos del objeto Post los cuales extraigo de una tabla pero no se el procedimiento completo. En tu ejemplo usas
$resultado = $this->Post->findById($id);
$this->set(‘datos_pdf’,$resultado);
Pero no entiendo como debo usar datos_pdf en el archivo cargar.ctp si me puedes aclarar esta duda te lo agradecería.
Buenas Juan,
Gracias por tu comentario!
Bueno te explico, lo que yo tengo es un ejemplo. Que puede ser algo que no necesitas, simplemente es ilustrativo. Por lo que es posible que tu no necesites asignar datos a la vista, o si… eso ya es lo que tu necesites.
Ahora bien te explico el ejemplo, lo que hago es recoger los datos del Modelo Post cuyo identificador sea $id. Bien.
Esto que se ha obtenido va a ser un array y lo seteo en la vista. con
Si tienes dudas lo primero que puedes hacer es un
en la vista, para comprobar que se ha seteado bien los datos y llegan a la vista. Si tienes problemas y te da errores, prueba a renderizar otro layout que no sea el de pdf, en la función del controller en vez de poner
pon
o cualquier otro layout que tengas creado para tu aplicación.
Y luego ya desde la vista vas colocando los datos de $datos_pdf donde necesites y en la posición que necesites en el html o en el pdf.
Ya lo resolvi utilizando $datos_pdf como sigue:
$tcpdf->Cell(60,20,$datos_pdf['Post']['title'], 0, 10);
Ahora tengo otra duda. Cuando utilizo cualquiera de los ejemplos de http://www.tcpdf.org/examples.php obtengo el siguiente error:Fatal error: require_once() [function.require]: Failed opening required ‘../tcpdf.php’
Pedro y muchas gracias por tomar un poco de tu tiempo para aclarar en forma tan explicita la duda que tenia!
Pedro encontre una manera (forma absoluta) de usar los ejemplos de http://www.tcpdf.org/examples.php:
Tomo cualquiera de los ejemplos y lo agreo como una accion del controlador Post, en este caso la llame imprimir.ctp; luego sustituyo tanto en require_once(‘../config/lang/eng.php’) como en
require_once(‘../tcpdf.php’); colocando la ruta completa donde se encuentran respectivamente tcpdf.php y eng.php asi:
require_once(‘Unidad:/ruta/completa/config/lang/eng.php’);
require_once(‘Unidad:/ruta/completa/tcpdf/tcpdf.php’); (funciono usando ‘/’ o usando ‘\’ aunque creo que debe haber una manera mas elegante de indicar la ruta en forma relativa).
Lo puedes hacer con el require_once como haces, pero lo suyo es incluirlo como Vendor, App::import(‘Vendor’,'tcpdf/tcpdf’);
Luego para la barra, utiliza la constante DS, que sirve para pintar los separadores.
require_once(‘Unidad:’.DS.’ruta’.DS.’completa’.DS.’tcpdf’.DS.’tcpdf.php’);
Gracias por esa recomendacion. Estoy tratando de implementarla. Sin embargo se me esta presentando un problema con algunos ejemplos, cuando los trato de usar me aparece el siguiente error: “el archivo no empieza por ‘ %pdf-’”; he buscado una solucion a través del buscador de google pero ninguna me ha funcionado. Estoy usando la ultima version de Wampserver (2.1) y las versiones 6 y 9 de Adobe Reader… ¿Tienes alguna idea que me sugieras Pedro? Gracias!
Eso mismo me pasó hace mucho tiempo, pero no recuerdo muy bien como lo solucioné… vaya tenía que haber documentado ese error en su día.
Creo que puede venir por que tienes algun espacio en blanco, o algo relacionado en la vista, como te digo no recuerdo muy bien.
Si quieres usa este código de ejemplo que te paso, que es el que tengo en una de mis vistas y que funciona ok
<?php App::import('Vendor','xtcpdf'); $tcpdf = new XTCPDF(); $textfont = 'freesans'; // looks better, finer, and more condensed than 'dejavusans' $tcpdf->SetAuthor(""); $tcpdf->SetAutoPageBreak( false ); $tcpdf->setHeaderFont(array($textfont,'',10)); $tcpdf->xheadercolor = array(255,255,255); $tcpdf->xheadertext = ''; $tcpdf->xfootertext = ''; // Now you position and print your page content // example: $tcpdf->AddPage(); $tcpdf->SetTextColor(0, 0, 0); // test Cell stretching // set JPEG quality $htmlcontent = '<img src="http://www.pedroventura.com/images/logo.jpg" /><p>Destinatario:</p>'; // output the HTML content $tcpdf->writeHTML($htmlcontent); //$tcpdf->setJPEGQuality(100); //$tcpdf->Image('http://www.todopapas.com/img/logo_tpp.jpg'); //$tcpdf->Cell(0, 10, 'Destinatario:', 0, 1, null, 0, '', 0); $tcpdf->Cell(0, 10, strtoupper($datos_user['User']['nombre']).' '.strtoupper($datos_user['User']['apellidos']), 0, 1, null, 0, '', 0); $tcpdf->Cell(0, 10, strtoupper($datos_user['User']['direccion']), 0, 1, null, 0, '', 0); $tcpdf->Cell(0, 10, strtoupper($datos_user['User']['localidad']), 0, 1, null, 0, '', 0); $tcpdf->Cell(0, 10, $datos_user['User']['cp'].' '.strtoupper($datos_user['GeoIntProvincia']['provincias_nombre']), 0, 1, null, 0, '', 0); $tcpdf->Cell(0, 10, $datos_user['User']['tlf'], 0, 1, null, 0, '', 0); echo $tcpdf->Output('filename.pdf', 'I'); ?>Ya resolvi el problema “el archivo no empieza por ‘ %pdf-’ “: Cuando copiaba y pegaba el codigo de los ejemplos dentro del imprimir.ctp se insertaba una linea en blanco con caracteres extraños. Solo repeti la operacion de copiar y pegar en forma “limpia” sin pegar espacios o carecteres extraños al final de linea. Pedro todavia tengo dudas para usar el App::import(‘Vendor’,’tcpdf/tcpdf’) que me sugeristes pero estoy en eso.
me alegro!! bueno como tenia la sensación tenia que ser algún carácter raro o espacio en blanco. Sobre lo del App::Import, de que tienes dudas? no te entiendo muy bien. App::Import en cakephp no es mas que un include() de php. No te lies mucho con esto es muy simple.
Que tal Pedro, como estas? Con respecto al último comentario que me enviastes sobre el uso del App::import() le he “hechado cabeza” y sigo con dudas sobre su uso. El problema comienza con las instrucciones require_once(‘../config/lang/eng.php’);
require_once(‘../tcpdf.php’); que como te comente no me funcionaban, asi que coloque en ambas las rutas completas: require_once(‘ruta/completa/config/lang/eng.php’);
require_once(‘ruta/completa/tcpdf.php’); y asi si corrio. Tu me sugeristes usar App::import(‘Vendor’,’tcpdf/tcpdf’); las use para sustituir ambas instrucciones pero no se que partes de las rutas debo colocar (si es que tengo que colocar las rutas). En resumen solo me ha funcionado combinando las instrucciones asi tal cual como siguen: App::import(‘Vendor’,'tcpdf’); require_once(‘ruta/completa/tcpdf/config/lang/eng.php’); ¿Debo usar App::import para apuntar al archivo eng.php o la carpeta que lo contiene? y ¿Cómo indicar su ubicacion al App::import? Gracias!
Buenas Juan,
Bueno a ver creo que estas algo confuso.
Tal cual lo tienes ahora esta perfecto!!!
App::Import() te dije que es parecido a un require, pero bueno es algo más no te lo aclaré bien. Se usa para incluir librerías y clases. Por lo que para incluir un php que no es un clase no funciona, y me imagino que en tu /config/lang/eng.php no tendrás ninguna clase, y por esto cakephp no está incluyendo bien este archivo.
Entonces como lo tienes esta perfecto. Con App::Import importas la clase de tcpdf.php y con el requiere lo que tienes en /config/lang/eng.php
Por otro lado, te pregunto que es lo que tienes en /config/lang/eng.php??? Son textos? Porque si son textos para diferenciarlos de una versión en ingles, español, portugués, etc.. usa el sistema de internalizacion que trae cakephp “locale” que es una implementacion de los archivos .po de internacionalizacion.
Oye Pedro muchas gracias de verdad! No me habia fijado en el contenido de ese archivo. Voy a leer un poco más sobre el sistema de internacionalizacion de cakephp. Seguimos en contacto…
hola Sr Pedro Ventura, tendrá algún ejemplo pero para excel.xls? o alguna recomendación?
http://bakery.cakephp.org/articles/melgior/2010/01/26/simple-excel-spreadsheet-helper
http://bakery.cakephp.org/articles/janb/2007/04/05/generate-excel-spreadsheets-from-your-database
No he podido ver el pdf, cuando intento generarlo, no tira ningun error pero la pagina queda en blanco, probe variar los parametros de memoria que han explicado arriba pero sigo sin resultados, Muchas gracias!
Le pusiste el header de pdf header(“Content-type: application/pdf”); ??
Tienes el debug a 3? Mira el log de errores de apache que seguro te tiene que estar devolviendo algun error
Si activo debug en el controlador me tira esto:
Fatal error: Call to a member function charset() on a non-object in N:\www\hostcontrol\app\views\layouts\admin.ctp on line 4
en el log de apache:[Fri Sep 17 09:28:45 2010] [error] [client 127.0.0.1] PHP Fatal error: Call to a member function charset() on a non-object in N:\\www\\hostcontrol\\app\\views\\layouts\\admin.ctp on line 4, referer: http://hostcontrol.local/admin/people
Y si le puse el header por lo que decias antes, gracias
seguro te está fallando una linea en el layout: admin.ctp que será algo así
En tu controlador has incluido el helper de html??
var $helpers = array('Html');Cual es la ruta exacta para ver la descargar del PDF.
intento con web.com/mi_aplicacion/descargar y nada…
Gracias
pues la ruta depende, será miweb.com/controller/function que tengas. En este caso la function es descargar.
Mete en el boostrap.php
Configure::write('debug',3);para ver que error te está dando.
Eso… o puedes meter
function __construct() { parent::__construct(); configure::write('debug',3); }en el controlador donde has integrado esto del pdf
Primero hay que localizar el error u obtener más pistas del error que te pueda estar dando… sabes es una pregunta muy poco concreta
también puedes mirar en el error_log de apache
Hola primero que nada gracias por el tutorial, he buscado en google un par de horas y no consigo encontrar una solucion, segui tu tutorial pero me da un error al generar el pdf
TCPDF ERROR: Some data has already been output, can’t send PDF file
Ya revise todos mis archivos en busca de saltos antes de , tambien aplice el Configure::write(‘debug’,0); en el controlador y sigue dando el error
gracias
pues ese error parece algo de los header, le has puesto bien la cabecera??
lo tienes que renderizar en el layout pdf
< ?php
header("Content-type: application/pdf");
echo $content_for_layout;
?>
un problema común por el que da un error de headers es que haya algún espacio en blanco al final del controller…
Hola, tengo el mismo problema, lograste encontrar la solución? de antemano gracias!
Es extraño, pero al cambiar la I o la D en el view por una S, el archivo se ve, saludos
echo $tcpdf->Output(‘mi_archivo.pdf’, ‘S’);
Muy bien el articulo traducido, muchas gracias.
solo tuve un inconveniente, que la memoria era superada por este script, así que hacia falta corregir esto en la configuración del PHP, con:
Al inicio del script “app/views/mi_aplicacion/descargar.ctp”
ini_set(“memory_limit”,”12M”); // se incrementa tamaño hasta que sea el correcto
De nada! me alegro que te haya servido!