Cómo utilizar el tipo de datos BLOB de MySQL para almacenar imágenes con PHP en Ubuntu 18.04

El autor seleccionó Girls Who Code para recibir una donación como parte del programa Write for DOnations.

Introducción

El tipo de datos de gran objeto binario (BLOB) es un tipo de datos de MySQL que puede almacenar datos binarios como los de archivos de imagen, multimedia y PDF.

Al crear aplicaciones que requieren una base de datos estrechamente acoplada donde las imágenes deben estar sincronizadas con los datos relacionados (por ejemplo, un portal de empleados, una base de datos de estudiantes o una aplicación financiera), puede resultarle conveniente almacenar imágenes como las de fotos y firmas de pasaportes de estudiantes en una base de datos de MySQL junto con otra información relacionada.

Aquí es donde entra el tipo de datos BLOB de MySQL. Este enfoque de programación elimina la necesidad de crear un sistema de archivos independiente para almacenar imágenes. El esquema también centraliza la base de datos, haciéndola más portátil y segura porque los datos están aislados del sistema de archivos. Crear copias de seguridad también es más sencillo, ya que que puede crear un solo archivo MySQL dump que contenga todos sus datos.

La recuperación de datos es más rápida y, al crear registros, podrá estar seguro de que las reglas de validación de datos y la integridad referencial se preserven, en especial al utilizar transacciones en MySQL.

En este tutorial, utilizará el tipo de datos BLOB de MySQL para almacenar imágenes con PHP en Ubuntu 18.04.

Requisitos previos

Para completar esta guía, necesitará lo siguiente:

Paso 1: Crear una base de datos

Comenzará creando una base de datos de ejemplo para su proyecto. Para hacer esto, aplique SSH a su servidor y luego ejecute el siguiente comando para iniciar sesión en su servidor MySQL como root:

  • sudo mysql -u root -p

Ingrese la contraseña root de su base de datos de MySQL y presione INTRO para continuar.

Luego, ejecute el siguiente comando para crear una base de datos. En este tutorial, lo llamaremos test_company:

  • CREATE DATABASE test_company;

Una vez que cree la base de datos, verá el siguiente resultado:

Output
Query OK, 1 row affected (0.01 sec)

Luego, cree una cuenta test_user en el servidor de MySQL y recuerde reemplazar PASSWORD por una contraseña segura:

  • CREATE USER 'test_user'@'localhost' IDENTIFIED BY 'PASSWORD';

Verá el siguiente resultado:

Output
Query OK, 0 rows affected (0.01 sec)

Para otorgar a test_user privilegios completos respecto de la base de datos test_company, ejecute lo siguiente:

  • GRANT ALL PRIVILEGES ON test_company.* TO 'test_user'@'localhost';

Asegúrese de obtener el siguiente resultado:

Output
Query OK, 0 rows affected (0.01 sec)

Por último, elimine la tabla de privilegios para que MySQL vuelva a cargar los permisos:

  • FLUSH PRIVILEGES;

Asegúrese de ver el siguiente resultado:

Output
Query OK, 0 rows affected (0.01 sec)

Ahora que la base de datos test_company y test_user están listos, continúe creando una tabla products para almacenar productos de ejemplo. Más adelante, utilizará esta tabla para insertar y obtener registros a fin de demostrar cómo funciona BLOB de MySQL.

Cierre sesión en el servidor de MySQL:

  • QUIT;

Luego, vuelva a iniciar sesión con las credenciales de test_user que creó:

  • mysql -u test_user -p

Cuando se le solicite, ingrese la contraseña de test_user y presione ENTER para continuar. Luego, posiciónese en la base de datos test_company escribiendo lo siguiente:

  • USE test_company;

Una vez que seleccione la base de datos test_company, MySQL mostrará lo siguiente:

Output
Database changed

Luego, cree una tabla products ejecutando lo siguiente:

  • CREATE TABLE `products` (product_id BIGINT PRIMARY KEY AUTO_INCREMENT, product_name VARCHAR(50), price DOUBLE, product_image BLOB) ENGINE = InnoDB;

Con este comando se crea una tabla llamada products. La tabla tiene cuatro columnas:

  • product_id: esta columna utiliza un tipo de datos BIGINT para admitir una gran lista de productos hasta un máximo de 2⁶³-1 artículos. Se marca la columna como PRIMARY KEY para identificar productos de manera exclusiva. Para que MySQL administre la generación de nuevos identificadores para columnas insertadas, utilizó la palabra clave AUTO_INCREMENT.

  • product_name: esta columna contiene los nombres de los productos. Se utiliza el tipo de datos VARCHAR, ya que este campo generalmente administra alfanuméricos de hasta un máximo de 50 caracteres; el límite de 50 es solo un valor hipotético utilizado para de este tutorial.

  • price: para fines demostrativos, su tabla products contiene la columna price que permite almacenar el precio minorista de los productos. Dado que algunos productos pueden tener valores flotantes (por ejemplo 23.69, 45.36, 102.99), se utiliza el tipo de datos DOUBLE.

  • product_image: en esta columna se utiliza el tipo de datos BLOB para almacenar los datos binarios reales de las imágenes de los productos.

Se utiliza el ENGINE de almacenamiento InnoDB para que la tabla admita una amplia gama de funciones, incluso transacciones de MySQL. Después de ejecutar esto para crear la tabla products, verá el siguiente resultado:

Output
Query OK, 0 rows affected (0.03 sec)

Cierre la sesión de su servidor de MySQL:

  • QUIT;

Verá el siguiente resultado:

Output
Bye

La tabla products ahora está lista para almacenar algunos registros, incluidas las imágenes de los productos y, en el siguiente paso, la completará con algunos productos.

Paso 2: Crear secuencias de comandos PHP para conectar y completar la base de datos

En este paso, creará una secuencia de comandos PHP que se conectará a la base de datos MySQL que creó en el paso 1. La secuencia de comandos preparará tres productos de ejemplo y los insertará en la tabla products.

Para crear el código PHP, abra un nuevo archivo con su editor de texto:

  • sudo nano /var/www/html/config.php

Luego, ingrese la siguiente información en el archivo y reemplace PASSWORD por la contraseña test_user que creó en el paso 1:

/var/www/html/config.php
<?php

define('DB_NAME', 'test_company');
define('DB_USER', 'test_user');
define('DB_PASSWORD', 'PASSWORD');
define('DB_HOST', 'localhost');

$pdo = new PDO("mysql:host=" . DB_HOST . "; dbname=" . DB_NAME, DB_USER, DB_PASSWORD);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Guarde y cierre el archivo.

En este archivo, utilizó cuatro constantes PHP para conectarse a la base de datos MySQL que creó en el paso 1:

  • DB_NAME : esta constante contiene el nombre de la base de datos test_company.

  • DB_USER : esta variable contiene el nombre de usuario test_user.

  • DB_PASSWORD : esta constante almacena la PASSWORD de MySQL de la cuenta test_user.

  • DB_HOST: esto representa el servidor en el que se ubica la base de datos. En este caso, utilizará el servidor localhost.

Con la siguiente línea de su archivo se inicia un objeto de datos de PHP (PDO) y se conecta a la base de datos MySQL:

...
$pdo = new PDO("mysql:host=" . DB_HOST . "; dbname=" . DB_NAME, DB_USER, DB_PASSWORD);
...

Cerca del final del archivo, configuró algunos atributos PDO:

  • ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION: este atributo indica a PDO que inicie una excepción que se puede registrar para depuración.
  • ATTR_EMULATE_PREPARES, false: esta opción aumenta la seguridad al indicar al motor de la base de datos MySQL que realice la preparación en lugar de PDO.

Incluirá el archivo /var/www/html/config.php en dos secuencias de comandos PHP que creará luego para insertar y recuperar registros respectivamente.

Primero, cree la secuencia de comandos PHP /var/www/html/insert_products.php para insertar registros en la tabla de productos:

  • sudo nano /var/www/html/insert_products.php

Luego, añada la siguiente información al archivo /var/www/html/insert_products.php:

/var/www/html/insert_products.php
<?php

require_once 'config.php';

$products = [];

$products[] = [
              'product_name' => 'VIRTUAL SERVERS',
              'price' => 5,
              'product_image' => file_get_contents("https://i.imgur.com/VEIKbp0.png")
              ];

$products[] = [
              'product_name' => 'MANAGED KUBERNETES',
              'price' => 30,
              'product_image' => file_get_contents("https://i.imgur.com/cCc9Gw9.png")
              ];

$products[] = [
              'product_name' => 'MySQL DATABASES',
              'price' => 15,
              'product_image' => file_get_contents("https://i.imgur.com/UYcHkKD.png" )
              ];

$sql = "INSERT INTO products(product_name, price, product_image) VALUES (:product_name, :price, :product_image)";

foreach ($products as $product) {
    $stmt = $pdo->prepare($sql);
    $stmt->execute($product);
}

echo "Records inserted successfully";

Guarde y cierre el archivo.

En el archivo, incluyó el archivo config.php en la parte superior. Este es el primer archivo que creó para definir las variables de la base de datos y conectarse a la base de datos. El archivo también inicia un objeto PDO y lo almacena en una variable $pdo.

Luego, creó una matriz de datos de los productos que se insertarán en la base de datos. Aparte de product_name y price, que se preparan como cadenas y valores numéricos respectivamente, la secuencia de comandos utiliza la función file_get_contents integrada de PHP para leer imágenes de una fuente externa y pasarlas como cadenas a la columna product_image.

Luego, preparó una instrucción SQL y utilizó la instrucción foreach{...} de PHP para insertar cada producto en la base de datos.

Para ejecutar el archivo /var/www/html/insert_products.php, realice la ejecución en la ventana de su navegador utilizando la siguiente URL. Recuerde reemplazar your-server-IP por la dirección IP pública de su servidor:

http://your-server-IP/insert_products.php

Después de ejecutar el archivo, verá un mensaje de éxito en su navegador confirmando que los registros se insertaron en la base de datos.

Mensaje de éxito que indica que los registros se insertaron en la base de datos

Insertó con éxito tres registros que contienen imágenes de productos en la tabla products. En el siguiente paso, creará una secuencia de comandos PHP para obtener estos registros y mostrarlos en su navegador.

Paso 3: Mostrar la información de los productos de la base de datos MySQL

Con la información e imágenes de los productos en la base de datos, ahora debe codificar otra secuencia de comandos PHP que consulta y muestra la información de los productos en una tabla HTML en su navegador.

Para crear el archivo, escriba lo siguiente:

  • sudo nano /var/www/html/display_products.php

Luego, ingrese la siguiente información en el archivo:

/var/www/html/display_products.php
<html>
  <title>Using BLOB and MySQL</title>
  <body>

  <?php

  require_once 'config.php';

  $sql = "SELECT * FROM products";
  $stmt = $pdo->prepare($sql);
  $stmt->execute();
  ?>

  <table border = '1' align = 'center'> <caption>Products Database</caption>
    <tr>
      <th>Product Id</th>
      <th>Product Name</th>
      <th>Price</th>
      <th>Product Image</th>
    </tr>

  <?php
  while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
      echo '<tr>';
      echo '<td>' . $row['product_id'] . '</td>';
      echo '<td>' . $row['product_name'] . '</td>';
      echo '<td>' . $row['price'] . '</td>';
      echo '<td>' .
      '<img src = "data:image/png;base64,' . base64_encode($row['product_image']) . '" width = "50px" height = "50px"/>'
      . '</td>';
      echo '</tr>';
  }
  ?>

  </table>
  </body>
</html>

Guarde los cambios del archivo y ciérrelo.

Aquí, nuevamente incluyó el archivo config.php para establecer conexión con la base de datos. Luego, preparó y ejecutó una instrucción SQL utilizando PDO para obtener todos los elementos de la tabla products utilizando el comando SELECT * FROM products​​​.

Luego, creó una tabla HTML y la completó con los datos de los productos utilizando la instrucción PHP while() {...}​​​. La línea $row = $stmt->fetch(PDO::FETCH_ASSOC)​​​ consulta la base de datos y almacena el resultado en la variable $row como matriz multidimensional, que luego se mostró en una columna de la tabla HTML utilizando la sintaxis $row['column_name']​​​.

Las imágenes de la columna product_image se incluyen en el interior de las etiquetas <img src = "">. Se utilizan los atributos width y height para cambiar el tamaño de las imágenes por uno más pequeño que pueda caber en la columna de la tabla HTML.

Para convertir los datos contenidos en el tipo de datos BLOB de vuelta en imágenes, se utilizan la función base64_encode de PHP integrada y la siguiente sintaxis para el esquema URI de datos:

data:media_type;base64, base_64_encoded_data

En este caso, imagen/png es media_type y la cadena codificada Base64 de la columna product_image es base_64_encoded_data.

Luego, ejecute el archivo display_products.php en un navegador web escribiendo la siguiente dirección:

http://your-server-IP/display_products.php

Después de ejecutar el archivo display_products.php en su navegador, verá una tabla HTML con una lista de productos e imágenes asociados.

Lista de productos de la base de datos MySQL

Esto confirma que la secuencia de comandos de PHP para obtener imágenes de MySQL funciona según lo previsto.

Conclusión

A través de esta guía, utilizó el tipo de datos BLOB de MySQL para almacenar y mostrar imágenes con PHP en Ubuntu 18.04. También vio las ventajas básicas de almacenar imágenes en una base de datos respecto de hacerlo en un sistema de archivos. Entre ellas, se incluyen la portabilidad, la seguridad y la facilidad de respaldo. Si compila una aplicación, como un portal de estudiantes o una base de datos de empleados para los cuales se deban almacenar juntas la información y las imágenes relacionadas, esta tecnología puede resultarle muy útil.

Para obtener más información sobre los tipos de datos compatibles en MySQL, consulte la guía de tipos de datos de MySQL. Si está interesado en más contenido relacionado con MySQL y PHP, consulte los siguientes tutoriales:

Source: DigitalOcean