
Crear PDF con FPDF usando PHP & MySQL. En este artículo vamos a implementar un pequeño sistema para mostrar un reporte en extensión PDF usando la librería FPDF.
¿Cómo funciona el script?
Este script realiza el historial clínico de múltiples pacientes. Por lo tanto, a través de un CRUD mostraremos los datos del paciente y haciendo uso de un vínculo podemos ver los datos generales de dicho paciente y un resumen de las consultas médicas que realizó el paciente en la clínica, el reporte historial estará en formato PDF listo para la impresión.
Crear PDF con FPDF usando PHP & MySQL
Si deseamos lograr este objetivo utilizaremos varios compontes que detallaré a continuación:
- Lenguaje de programación PHP
- Gestor de base de datos MySQL
- Librería FPDF.
- HTML5
Crear PDF con FPDF: Estructura
A continuación, detallaremos los elementos y partes del script para el correcto funcionamiento del script.
Primer paso: Crear base de datos y tablas
Para este ejemplo necesitaremos 3 tablas con los siguientes nombres para armar nuestro reporte y estas son:
consultas_medicas. – Encargado de almacenar las consultas de todos los pacientes.
medicos. – Tabla que almacena a todos los médicos de la clínica
pacientes. – Tabla que almacena a todos los pacientes que se atienden en la clínica.
CREATE TABLE `consultas_medicas` ( `consulta_id` bigint(20) UNSIGNED NOT NULL, `fecha_consulta` date NOT NULL, `id_paciente` int(5) NOT NULL, `id_medico` int(5) NOT NULL, `consultorio` varchar(20) NOT NULL, `diagnostico` text NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `consultas_medicas` (`consulta_id`, `fecha_consulta`, `id_paciente`, `id_medico`, `consultorio`, `diagnostico`) VALUES (1, '2020-04-14', 1, 3, 'B-05', 'Sinusitis Aguda'), (2, '2020-05-11', 1, 1, 'A-09', 'Hematoma severa'), (3, '2020-06-17', 2, 2, 'B-06', 'Gastritis'), (4, '2020-07-18', 1, 3, 'D-90', 'Gripe aguda'), (5, '2020-08-19', 3, 2, 'Z-11', 'Fractura Clavicula'); CREATE TABLE `medicos` ( `medico_id` bigint(20) UNSIGNED NOT NULL, `cedula` varchar(10) NOT NULL, `nombre_medico` varchar(200) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `medicos` (`medico_id`, `cedula`, `nombre_medico`) VALUES (1, '78452596', 'Dr. Juan Medina'), (2, '74582125', 'Dr. Maria Prada'), (3, '96352145', 'Dr. Carlos Kim'), (4, '78965412', 'Dr. Luis Tejada'); CREATE TABLE `pacientes` ( `paciente_id` int(11) NOT NULL, `dni` varchar(10) NOT NULL, `nombre` varchar(80) NOT NULL, `apellido_paterno` varchar(80) NOT NULL, `apellido_materno` varchar(80) NOT NULL, `sexo` varchar(2) NOT NULL, `domicilio` text NOT NULL, `foto` varchar(250) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `pacientes` (`paciente_id`, `dni`, `nombre`, `apellido_paterno`, `apellido_materno`, `sexo`, `domicilio`, `foto`) VALUES (1, '45125236', 'Pedro', 'Carrillo', 'Gonzales', 'H', 'Av. Santiago Mayolo #2840', 'pedro.jpg'), (2, '21526356', 'Joaquin', 'Flores', 'Valencia', 'H', 'Av. Los molinos #41', 'joaquin.jpg'), (3, '74582145', 'Lucia', 'Espinoza', 'Zavaleta', 'F', 'Av. Los Florales #327', 'lucia.jpg'); ALTER TABLE `consultas_medicas` ADD PRIMARY KEY (`consulta_id`); ALTER TABLE `medicos` ADD PRIMARY KEY (`medico_id`); ALTER TABLE `pacientes` ADD PRIMARY KEY (`paciente_id`); ALTER TABLE `consultas_medicas` MODIFY `consulta_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6; ALTER TABLE `medicos` MODIFY `medico_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5; ALTER TABLE `pacientes` MODIFY `paciente_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
Segundo paso: Crear conexión
La conexión es importante y utilizaremos la clase conexión para conectar PHP con la base de datos. Sin embargo, para lograr la conexión usaremos mysqli.
Class Conexion { public function conectar(){ $mysqli = new mysqli('localhost','root','','db_clinica',3306); if ($mysqli->connect_errno) header('Location: /'); $mysqli->set_charset('utf8'); return $mysqli; } }
Tercer paso: Clase pacientes
Aquí creamos nuestra clase pacientes para listar en nuestro index.php y poder acceder a un enlace para generar el historial consultas médicas del paciente.
<?php require_once 'conexion.php'; class Paciente extends Conexion { public $mysqli; public $data; public function __construct() { $this->mysqli = parent::conectar(); $this->data = array(); } //***************************************************************** // LISTAMOS DE PACIENTES //***************************************************************** public function pacientes(){ $resultado = $this->mysqli->query("SELECT * FROM pacientes"); while( $fila = $resultado->fetch_assoc() ){ $data[] = $fila; } if (isset($data)) { return $data; } } //***************************************************************** // PACIENTE POR ID //***************************************************************** public function paciente_id($id){ $consulta = sprintf("SELECT * FROM pacientes WHERE paciente_id = %s", parent::comillas_inteligentes($id) ); $resultado = $this->mysqli->query($consulta); $fila = $resultado->fetch_array(); return $fila; } }
Cuarto paso: Clase consulta
Este aparado es importante porque crearemos la clase consulta para generar el listado de las consultas médicas del paciente en el reporte con extensión PDF.
<?php require_once 'conexion.php'; class Consulta extends Conexion { public $mysqli; public $data; public function __construct() { $this->mysqli = parent::conectar(); $this->data = array(); } //***************************************************************** // LISTAMOS DE CONSULTAS //***************************************************************** public function consultasPaciente($id){ $consulta = sprintf("SELECT consultas_medicas.fecha_consulta, consultas_medicas.consultorio, consultas_medicas.diagnostico, medicos.nombre_medico FROM consultas_medicas INNER JOIN medicos ON consultas_medicas.id_medico = medicos.medico_id WHERE consultas_medicas.id_paciente = %s", parent::comillas_inteligentes($id) ); $resultado = $this->mysqli->query($consulta); while( $fila = $resultado->fetch_assoc() ){ $data[] = $fila; } if (isset($data)) { return $data; } } }
Quinto paso: Crear el archivo index.php
Este fichero será primordial porque en él se mostrará una lista de pacientes. Además, haciendo uso de un botón podremos ver el historial clínico de un determinado paciente.
Esta tabla está conformada por HTML5 y datatables que es una extensión de jQuery para darle dinamismo a los resultados encontrados.
Para mostrar el historial clínico usaremos el método GET con el ID del paciente.
<?php require("class/paciente.php"); include "header.php"; $objpaciente = new Paciente(); $pacientes = $objpaciente->pacientes(); if(sizeof($pacientes) > 0){ ?> <table id="clinica" class="display table table-bordered table-stripe" cellspacing="0" width="100%"> <thead> <tr> <th>DNI</th> <th>NOMBRE</th> <th>GENERO</th> <th>DIRECCION</th> <th>HISTORIAL</th> </tr> </thead> <tbody> <?php foreach ($pacientes as $row){ ?> <tr> <td><?php echo $row['dni']; ?></td> <td><?php echo $row['nombre'].' '.$row['apellido_paterno'].' '.$row['apellido_materno']; ?></td> <td><?php echo $row['sexo']; ?></td> <td><?php echo $row['domicilio']; ?></td> <td> <a href="historial.php?id=<?php echo $row['paciente_id'] ?>"><span class="glyphicon glyphicon-file" aria-hidden="true"></span> Historial Clinico</a> </td> </tr> <?php } ?> </tbody> </table> <?php }else{ echo "No hay resultados..."; } include "footer.php";
Sexto paso: Historial.php
Sera el encargado de mostrar el documento PDF en donde podemos observar las consultas que realizo el paciente en la clínica, listada por fecha de atención, médico que lo atendió y el diagnostico.
<?php require('fpdf/fpdf.php'); require("class/paciente.php"); require("class/consulta.php"); class PDF extends FPDF { var $widths; var $aligns; function SetWidths($w) { $this->widths=$w; } function SetAligns($a) { $this->aligns=$a; } function Row($data) { $nb=0; for($i=0;$i<count($data);$i++) $nb=max($nb,$this->NbLines($this->widths[$i],$data[$i])); $h=8*$nb; $this->CheckPageBreak($h); for($i=0;$i<count($data);$i++) { $w=$this->widths[$i]; $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; $x=$this->GetX(); $y=$this->GetY(); $this->Rect($x,$y,$w,$h); $this->MultiCell($w,8,$data[$i],0,$a,'true'); $this->SetXY($x+$w,$y); } $this->Ln($h); } function CheckPageBreak($h) { if($this->GetY()+$h>$this->PageBreakTrigger) $this->AddPage($this->CurOrientation); } function NbLines($w,$txt) { $cw=&$this->CurrentFont['cw']; if($w==0) $w=$this->w-$this->rMargin-$this->x; $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; $s=str_replace("\r",'',$txt); $nb=strlen($s); if($nb>0 and $s[$nb-1]=="\n") $nb--; $sep=-1; $i=0; $j=0; $l=0; $nl=1; while($i<$nb) { $c=$s[$i]; if($c=="\n") { $i++; $sep=-1; $j=$i; $l=0; $nl++; continue; } if($c==' ') $sep=$i; $l+=$cw[$c]; if($l>$wmax) { if($sep==-1) { if($i==$j) $i++; } else $i=$sep+1; $sep=-1; $j=$i; $l=0; $nl++; } else $i++; } return $nl; } function Header() { $this->SetFont('Arial','',10); $this->Text(20,14,'Historial clinico - Clinica la Luz',0,'C', 0); $this->Ln(10); } function Footer() { $this->SetY(-15); $this->SetFont('Arial','B',8); $this->Cell(100,10,'Historial del paciente',0,0,'L'); } } // Obtenemos el id del paciente $paciente_id= $_GET['id']; // Creamos nuestro objeto paciente $objpaciente = new Paciente(); // obtenemos los datos del paciente por el id $paciente = $objpaciente->paciente_id($paciente_id); // Creamos nuestro objeto pdf $pdf=new Pdf(); // Agregamos una pagina al archivo $pdf->AddPage(); // Personalizamos los amrgenes $pdf->SetMargins(20,20,20); // Creamos un espacio $pdf->Ln(10); // Definimos la fuente y tamaño $pdf->SetFont('Arial','',12); // Creamos una celda para mostrar la información $pdf->Cell(30,6,'DNI: ',0,0); $pdf->Cell(0,6,$paciente['dni'],0,1); $pdf->Cell(30,6,'NOMBRE: ',0,0); $pdf->Cell(0,6,$paciente['nombre'].' '.$paciente['apellido_paterno'].' '.$paciente['apellido_materno'],0,1); $pdf->Cell(30,6,'SEXO: ',0,0); $pdf->Cell(0,6,$paciente['sexo'],0,1); $pdf->Cell(30,6,'DOMICILIO: ',0,0); $pdf->Cell(0,6,$paciente['domicilio'],0,1); // Usamos la funcio imagen, para obtenr la ruta de la imagen usamos nuestra funcion ruta de conexion $pdf->Image(Conexion::ruta().'upload/pacientes/'.$paciente['foto'],155,20,30,30); $pdf->Ln(10); $pdf->SetWidths(array(10, 20, 50, 50, 40)); $pdf->SetFont('Arial','B',10); $pdf->SetFillColor(29,29,29); $pdf->SetTextColor(255); // usamos nuestra funcion creada para listar celdas con varias lineas $pdf->Row(array('#','FECHA', 'MEDICO', 'CONSULTORIO', 'DIAGNOSTICO')); // Creamos nuestra funcion consulta $objconsulta = new Consulta(); $consultas = $objconsulta->consultasPaciente($paciente_id); $i = 0; // listamos las consultas $n=0; foreach ($consultas as $consulta) {$n++; $pdf->SetFont('Arial','',9); if($i%2 == 1){ $pdf->SetFillColor(181,175,173); $pdf->SetTextColor(0); $pdf->Row(array($n,$consulta['fecha_consulta'], $consulta['nombre_medico'], $consulta['consultorio'], $consulta['diagnostico'])); $i++; }else{ $pdf->SetFillColor(212,204,202); $pdf->SetTextColor(0); $pdf->Row(array($n,$consulta['fecha_consulta'], $consulta['nombre_medico'], $consulta['consultorio'], $consulta['diagnostico'])); $i++; } } // Salida del archivo y nombre $pdf->Output('reporte.pdf','I'); ?>
Conclusión
- En este breve artículo hemos aprendido a manejar un CRUD en PHP con un listado de pacientes.
- Para mostrar las consultas de los pacientes hemos aprendido a manejar la librería FPDF para visualizar el reporte en formato PDF
- Hemos aprendo a darle colores, ancho personalizado a las celdas de tablas y exporta en PDF
Script corregido y actualizado
Saludos. Excelente explicacion y muy buena ejemplos. Tengo una consulta: Me funciona correctamente en localhost, pero cuando lo paso a la web funciona, solo que cuando doy clic en historial clinico no me genera el pdf….podrias guiarme…
Gracias.
Hola howard
Echale un vistazo a la versión del PHP, verifica que version trabaja en localhost y luego verifica la versión del PHP de tu servidor.
Otro detalle puede ser las rutas de carpetas.
Saludos
Saludos Nestor.
gracias por responder.
Mira las versiones del php son
localhost es: PHP Version 5.6.39
servidor web es: PHP Version 8.1.13
creería que debería correr normal el script. cierto ¿?
En cuanto a las carpetas as copie tal cual están. Reitero en localhost me funciona perfecto. el detalle esta al dar clic en generar historial clínico en la web, se queda con la ruta en en navegador: http://xxxxxxx/xxxxxxxx/historial.php?id=1.
tanto para cada uno de los items existentes en la DB
Saludos nuevamente Nestor:
mira estas lineas:
Dice que en la 32 es donde me da error segun el error_log
Uncaught Error: Call to undefined function get_magic_quotes_gpc() in /home/xxxxxxxx/xxxxxxxxxxxxx/xxxxxxx/class/conexion.php:32
*-* linea 32 aqui abajo en: if (get_magic_quotes_gpc()) {
public function comillas_inteligentes($valor) {
// Retirar las barras
if (get_magic_quotes_gpc()) {
$valor = stripslashes($valor);
}
// Colocar comillas si no es entero
if (!is_numeric($valor)) {
$valor = «‘» . $this->mysqli->real_escape_string($valor) . «‘»;
}
return $valor;
}
}
Hola Howard
La función get_magic_quotes_gpc() ha quedado Obsoleta a partir de PHP 7.4.0. Si desea usar esta funcion es preciso usar versión de PHP inferiores a 7.4.
Según PHP no es recomendable usar esa función, he eliminado esa función y he actualizado el script para su descarga, revise en la parte final de este artículo.
Saludos cordiales
Nestor.
Buenos Días.
Efectivamente era esa linea. Agradezco mucho tu apoyo y tiempo.
Ya funcionó.
Muchas Gracias Nestor.
Feliz Navidad !!!
Buenas tardes Nestor.
Al instalar tu aplicación me funciona perfectamente salvo que se ve todo el código que hay insertado en la base de datos como pueden ser las b de negrita o las p de los párrafos por poner 2 ejemplos.
¿Hay alguna forma de que se vea solo el texto como en cualquier pagina html?
Gracias por adelantado.
seguro no estas lanzando correctamente tu app, no puedes estar abriendo dandole clic derecho al archivo e iniciar con un navegador, debes al menos instalar xampp y correrlo con el servidor de apache