jueves, 27 de junio de 2019

Grabar y mostrar imágenes con PHP y MySQL


El presente tutorial nos mostrará como almacenar imágenes en MySQL utilizando PHP

Herramientas usadas

  • WAMP - Versión 3.1.7
  • Apache - Versión 2.4.37
  • PHP - Versión 7.3.1
  • MySQL - Versión 5.7.24
  • MariaBD - Versión 10.3.12
Se puede utilizar MySQL o MariaBD, simplemente cambiar el puerto 3306 del MySQL por el 3307 de MariaBD.

Base de datos utilizada

-- TABLA ESTADO 
CREATE TABLE estado ( 
   id INT NOT NULL AUTO_INCREMENT ,
   nombres VARCHAR(100) NOT NULL ,
   PRIMARY KEY (id)
)ENGINE = InnoDB CHARSET=utf8 COLLATE utf8_general_ci;
/* DATOS DE INICIO */
INSERT INTO estado(nombres) VALUES 
   ('soltero'), 
   ('casado'), 
   ('divorciado'), 
   ('viudo')

-- TABLA PERSONAS 
CREATE TABLE personas ( 
   id INT NOT NULL AUTO_INCREMENT ,
   paterno VARCHAR(150) NOT NULL , 
   materno VARCHAR(150) NOT NULL , 
   nombres VARCHAR(100) NOT NULL , 
   estado INT NOT NULL ,
   foto MEDIUMBLOB NULL , 
   fecha_nacimiento DATE NOT NULL , 
   PRIMARY KEY (id),                 /* CLAVE PRIMARIA */
   CONSTRAINT fk_estado              /* CLAVE FORÁNEA  */
      FOREIGN KEY (estado)
      REFERENCES estado (id)
      ON DELETE NO ACTION
      ON UPDATE NO ACTION
)ENGINE = InnoDB CHARSET=utf8 COLLATE utf8_general_ci;

-- DATOS DE PRUEBA
INSERT INTO personas(paterno, nombres, materno, 
                     estado, fecha_nacimiento) VALUES
   ('Flores','Lucero','Diaz',1 ,'2000-06-05'),
   ('Mesa','Flor','Ochoa',4 ,'1990-01-01'),
   ('Vela','Mario','Roca',2 ,'1985-12-15'),
   ('Ruiz','Pedro','Gamboa',3 ,'2002-02-24')

--VISTA A DETALLE
CREATE VIEW personas_detalle AS
SELECT personas.id id, personas.paterno paterno, 
       personas.materno materno, personas.nombres nombres,
       estado.nombres estado ,personas.foto foto, 
       personas.fecha_nacimiento fecha_nacimiento
FROM personas INNER JOIN estado ON personas.estado = estado.id


Creando el archivo de configuración

Creamos el documento: config.php
<?php
date_default_timezone_set("America/Lima");
define("DB_HOST", "localhost");
define("DB_USER", "root");   # Usuario root
define("DB_PASSWORD", "");   # Sin contraseña
define("DB_NAME", "blog");   # Nombre de la base de datos
define("DB_PORT", "3306");   # Puerto 3306 - MySQL, 3307 - MariaBD


Creando la conexión y funciones básicas

Existen dos formas, de crear el archivo de conexión:
  • Mediante un archivo simple de conexión
  • Mediante una clase
Y existen dos formas de realizar la conexión:
  • Usando mysqli
  • Usando PDO
En este caso haremos el más sencillo que es un archivo simple y mysqli
Creamos un archivo llamado: biblioteca_mysql.php

<?php
include_once('config.php');
$cnx = '';

/**
 * Función para Conectarse a la base de datos
 */
function bd_conectar() {
    global $cnx;
    $cnx = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, DB_PORT);
    mysqli_query($cnx, "set names utf8");
}

/**
 * Función para desconectarse de la base de datos
 */
function bd_desconectar() {
    global $cnx;
    mysqli_close($cnx);
}

/**
 * Función para realizar consultas (SELECT) a la base de datos
 */
function bd_consultar($sql) {
    global $cnx;
    $bolsa = mysqli_query($cnx, $sql);
    $salida = array();
    if ($bolsa != null) {
        while ($row = mysqli_fetch_assoc($bolsa)) {
            $salida[] = $row;
        }
        mysqli_free_result($bolsa);
    } else {
        $salida = false;
    }
    unset($row);
    return $salida;
}

/**
 * Función para ejecuciones INSERT, UPDATE o DELETE a la base de datos
 */
function bd_ejecutar($sql) {
    global $cnx;
    $exito = mysqli_query($cnx, $sql);
    if ($exito) {
        return true;
    } else {
        return false;
    }
}


Función para cargar la imagen

Creamos un archivo que permite insertar y editar registros: editar_grabar.php


<?php
include_once 'biblioteca_mysql.php';
$id = $_POST['txtid'];
$pat = $_POST['txtpat'];
$mat = $_POST['txtmat'];
$nom = $_POST['txtnom'];
$fec = $_POST['txtcum'];
$est = $_POST['cboestado'];

$existFoto = false;

if (file_exists($_FILES['foto']['tmp_name'])) {
    #Extraemos el contenido de la imagen
    $fp = fopen($_FILES['foto']['tmp_name'], 'rb');
    $imagen = fread($fp, filesize($_FILES['foto']['tmp_name']));
    $imagen = addslashes($imagen);
    fclose($fp); #Cerramos imagen
    $existFoto = true;
}

if ($_POST['txtid'] == '') {
    $sql = "INSERT INTO personas (paterno, materno, nombres, estado";
    $sql .= ($existFoto) ? ", foto" : "";
    $sql .= ", fecha_nacimiento) values('$pat','$mat','$nom','$est'";
    $sql .= ($existFoto) ? ", '$imagen'" : "";
    $sql .= ",'$fec ')";
} else {
    $id = $_POST['txtid'];
    $sql = "UPDATE personas SET paterno = '$pat', materno = '$mat',";
    $sql .= " nombres = '$nom', fecha_nacimiento = '$fec', ";
    $sql .= "estado = $est";
    $sql .= ($existFoto) ? ", foto = '$imagen'" : "";
    $sql .= " WHERE id = $id";
}

unset($existFoto);

bd_conectar();
if (bd_ejecutar($sql)) {
 bd_desconectar();
 header('location: index.php');
} else {
 echo "Error al procesar el registro:<br/>";    
 echo '<a href="index.php">Regresar</a>';
 bd_desconectar();
}


Función para mostrar la imagen

Agregamos la función bd_ejecutar al archivo llamado: mostrar_imagen.php


<?php
include_once 'biblioteca_mysql.php';
$id=$_GET['id'];
bd_conectar();
$sql="SELECT foto FROM personas WHERE id='$id'";
$rpta=mysqli_query($cnx,$sql);
$pers=mysqli_fetch_assoc($rpta);
header("Content-type: image/png");
echo $pers['foto'];
bd_desconectar();


Creando una interfaz (Tablas y formularios)

Creamos un archivo llamado: personas.php
Aquí llamamos al documento PHP que contiene las funciones de conexión y para ejecutar sentencias SQL, recorriendola mediante un FOREACH en una tabla.

<?php
include_once 'biblioteca_mysql.php';
$sql = "SELECT * FROM personas_detalle";
bd_conectar();
$registros = bd_consultar($sql);
bd_desconectar();
?>
<!DOCTYPE html>
<html>
<head>
    <title>Reporte de inscritos</title>
</head>
<body><br/><br/>
<a class="boton" href="nuevo_formulario.html">Nuevo Registro</a><br/>
<table>
    <caption><b>Reporte de Personas</b></caption>
    <thead>
        <th>ID</th>
        <th>APELLIDO PATERNO</th>
        <th>APELLIDO MATERNO</th>
        <th>NOMBRES</th>
        <th>CUMPLEAÑOS</th>
        <th>ESTADO CIVIL</th>
        <th>FOTO</th>
        <th>ACCIONES</th>
    </thead>
    <tbody>
        <?php foreach ($registros as $persona) {?>
        <tr> 
          <td><?= $persona['id'] ?></td>
          <td><?= $persona['paterno'] ?></td>
          <td><?= $persona['materno'] ?></td>
          <td><?= $persona['nombres'] ?></td>
          <td><?= $persona['fecha_nacimiento'] ?></td>
          <td><?= strtoupper($persona['estado']) ?></td>
          <td>
            <img 
                src="mostrar_imagen.php?id=<?= $persona['id']; ?>"
            height="50"/>
          </td>
          <td>
            <a href="editar_formulario.php?id=<?= $persona['id'] ?>">
               EDITAR
            </a>
            <a href="borrar.php?id=<?= $persona['id'] ?>" 
               onclick="return confirm('¿Deseas borrar el registro?')">
               BORRAR
            </a>
          </td>
        </tr>
        <?php } ?>
    </tbody>
</table><br/>
</body>
</html>


Creamos un archivo llamado: editar_formulario.php

<?php
include_once 'biblioteca_mysql.php';
$rotulo = "AGREGAR";
if (isset($_GET['id'])){
 $id = $_GET['id'];$sql = "SELECT * FROM personas WHERE id = $id";
 $rotulo = "MODIFICAR"; 
 bd_conectar();
 $registros = bd_consultar($sql);
 $persona = $registros[0];
 unset($registros);
 bd_desconectar();
}else {
    $persona = null;
}
?>
<!DOCTYPE html>
<html>
<head>
    <title><?= $rotulo ?> PERSONA</title>
</head>
<body>
<form enctype="multipart/form-data" name="formulario_grabar_editar" 
         method="POST" action="editar_grabar.php">
    <input type="text" name="txtid"  value="<?= $persona['id']?>" 
           hidden="hidden" readonly="readonly"><br/>
    Apellido paterno:<br/>
 <input type="text" name="txtpat" value="<?= $persona['paterno']?>"
           placeholder="Ingrese su apellido paterno" maxlength="25"><br/>
    <br/>Apellido materno:<br/>
 <input type="text" name="txtmat" value="<?= $persona['materno']?>"
           placeholder="Ingrese su apellido materno" maxlength="25"><br/>
    <br/>Nombres:<br/>
 <input type="text" name="txtnom" value="<?= $persona['nombres']?>"
           placeholder="Ingrese sus nombres" maxlength="25"><br/>
    <br/>Fecha de nacimiento:<br/>
 <input type="date" name="txtcum" value="<?= $persona['fecha_nacimiento']?>"
           placeholder="Ingrese su fecha de nac."><br/>
    <br/>Seleccionar estado civil: 
    <select name="cboestado">
        <option>Seleccione</option>  
        <option value="1" <?=$persona['estado']==1 ? 'selected' : '' ?> >
                   Soltero</option>
        <option value="2" <?=$persona['estado']==2 ? 'selected' : '' ?> >
                   Casado</option>
        <option value="3" <?=$persona['estado']==3 ? 'selected' : '' ?> >
                   Divorciado</option>
        <option value="4" <?=$persona['estado']==4 ? 'selected' : '' ?> >
                   Viudo</option>
  
    </select><br/>    
    Foto:<input type="file" name="foto">
    <br/><br/>
    <input type="submit" name="btnGrabar" value="<?= $rotulo ?>">
</form>
</body>
</html>



Resultado

Página Index

Lo ideal es subir las imágenes al servidor y almacenar la URL en la base de datos, pero en caso de imágenes de alto valor o muy "sensibles". Se puede optar por almacenar dicha imagen u otro tipo de archivo como un instalador en la base de datos.


No hay comentarios:

Publicar un comentario