Guardar Imágenes en MySQL con PHP

Para evitar polémica, voy a comenzar esta entrada con una recomendación: ¡No lo hagas, a menos que realmente lo necesites! (pero si tienes decidido hacerlo, y entiendes los problemas asociados, pasa directamente a la siguiente sección donde está el código de ejemplo 🙂 Y ¿Porqué escribir un artículo sobre algo que no recomiendo? pues bueno,…


Guardar usuario con imagen - Layout

Para evitar polémica, voy a comenzar esta entrada con una recomendación: ¡No lo hagas, a menos que realmente lo necesites! (pero si tienes decidido hacerlo, y entiendes los problemas asociados, pasa directamente a la siguiente sección donde está el código de ejemplo 🙂

Y ¿Porqué escribir un artículo sobre algo que no recomiendo? pues bueno, hay situaciones en las cuales guardar las imágenes en base de datos es buena idea, pero veamos primero porqué generalmente no lo es.

Si las imágenes están guardadas en base de datos, entonces no serán directamente accesibles por un url, así que será tu responsabilidad buscar las imágenes en la base de datos y enviarlas al navegador, ya sea incrustadas directamente en el html (mediante Base64, que luego veremos), o enviarlas vía ajax, o implementar un controlador encargado de traducir las url de las imágenes solicitadas en consultas a la base de datos; todo esto hará difícil manejar el cacheado de las imágenes. Además, está el tamaño de la base de datos, que puede crecer enormemente si guardas las imágenes allí, afectando el rendimiento de la carga de imágenes y el resto de las consultas a la base de datos. La recomendación general que he visto en la Web es guardar el nombre y/o ruta de la imagen en base de datos, pero guardar el archivo de la imagen con un nombre único en una carpeta.

Por otro lado, hay situaciones en las podría ser más conveniente (o al menos no ser un problema) guardar las imágenes en base de datos; por ejemplo, cuando son pocas imágenes (como las fotos de perfil) y quieres impedir que se cacheen (incrustándolas en el html), o si simplemente no necesitas usar urls porque incrustarás las imágenes directamente en emails o pdfs, haciendo la caché innecesaria.

En fin, si ya decidiste que necesitas guardar las imágenes en base de datos, aquí está el código para hacerlo.

Enviar la imagen a PHP, vía AJAX

Bueno, el caso es el siguiente:

Tenemos una Web donde un administrador puede crear usuarios con un id (numérico), un nombre y una foto de perfil, el administrador puede también cambiar el nombre o imagen de un usuario existente. Se requiere programar un formulario (html+css+js) que permita crear y modificar usuarios (PHP), la foto de perfil se guardará en una base de datos (MySQL). Por ahora no será necesario guardar otros datos del usuario ni se requiere eliminarlos desde la interfaz.

Para cumplir con el requerimiento vamos a crear tres archivos:

  • guardar.html: formulario con controles para que el administrador ingrese los datos de los usuarios. Aquí usaremos HTML, CSS y Javascript.
  • guardar_imagen.php: tendrá el código que inserta o actualiza los datos del usuario, incluyendo el guardado de la imagen. La respuesta de este script será siempre en formato JSON.
  • utilidades.php: tendrá una función para responder en caso de errores (los detalles más adelante), y otra para abrir una conexión a la base de datos.

Comenzaremos por la interfaz; este será el html y css de nuestro formulario:

<!DOCTYPE HTML>
<html lang="es">
  <head>
    <meta charset="utf-8">
    <title>Guardar usuario con imagen</title>
    <style type="text/css">
      body {margin: 0px; padding: 0px;}
      .Seccion {width: 400px; margin: 0.5em; background-color: #DDDDDD;}
      #vistaPrevia {background-color: #FFFFFF; vertical-align: top; border: 1px solid #444444;
      }
    </style>
  </head>
  <body>
    <!-- Layout  -->
    <div class="Seccion">
      <h2>Crear/Actualizar Usuario</h2>
      <label for="idUsuario" >ID (entero):</label>
      <input id="idUsuario" type="text" /><br/>
      <label for="nombreUsuario" >Nombre:</label>
      <input id="nombreUsuario" type="text" /><br/>
      <label for="imagenUsuario" >Imagen:</label>
      <input id="seleccionarImagen" type="file" />
      <img id="vistaPrevia" /><br/>
      <input id="actualizarUsuario" type="button" value="Actualizar Usuario..." />
    </div>
    <!-- Javascript  -->
    <script type="text/javascript" src="../externas/jquery-2.0.3.min.js"></script>
    <script>
      //El código Javascript lo verás más abajo...
    </script>
  </body>
</html>


El formulario anterior consta de un par de inputs, con sus respectivas etiquetas, para ingresar el ID y el nombre del usuario, un botón (o más precisamente un fileinput) para seleccionar una imagen como foto de perfil, junto con un img para mostrar una vista previa de la misma; y finalmente un botón para enviar los datos al servidor para crear al nuevo usuario (si el ID no existe) o para actualizar su nombre y foto (si el ID ya está registrado).

Fíjate a final del HTML. Allí cargaremos jQuery (para hacer el trabajo más cómodo) y nuestro script, que verás un poco más abajo.

Guardar usuario con imagen - Layout

Lo siguiente es el código Javascript que enviará al servidor los datos del usuario para crearlo o actualizarlo. Veamos:

jQuery('#seleccionarImagen').on('change', function(e) {
  var Lector,
      oFileInput = this;
  if (oFileInput.files.length === 0) {
    return;
  };
  Lector = new FileReader();
  Lector.onloadend = function(e) {
    jQuery('#vistaPrevia').attr('src', e.target.result);
  };
  Lector.readAsDataURL(oFileInput.files[0]);
});
jQuery('#actualizarUsuario').on('click', function(e) {
  e.preventDefault();
  var parametros = {
    id : jQuery('#idUsuario').val(),
    nombre : jQuery('#nombreUsuario').val(),
    imagen : jQuery('#temporal').attr('src')
  };
  $.ajax('guardar_imagen.php', {
    type : 'post',
    data : parametros,
    success : function(data) {
      if(data.error){
        console.log('Error controlado.', data.mensaje);
        return;
      };
      console.log('Los datos del usuario ' + parametros.id + ' fueron guardados.');
    },
    error : function(data) {
      console.log('Error no controlado.', data);
    }
  });
  return false;
});

El código consiste en dos controladores de eventos. El primero detecta cuando el usuario selecciona una imagen y genera una vista previa a partir de ella (en mi artículo Vista previa de imagen en el navegador puedes ver más información al respecto). En resumen, este controlador leerá la imagen seleccionada en el control fileinput, y la copiará al elemento img.

El segundo controlador se encargará de enviar al servidor los datos para actualizar cuando el usuario haga clic en el botón correspondiente. Este código primero busca los datos a enviar (ID, nombre e imagen) y los almacena en el objeto parametros (¿te parece raro que leamos la imagen de img en lugar del inputfile? en la sección final te explicaré porqué… sigamos); luego lo envía mediante un post, con jQuery, al archivo guardar_imagen.php que esperará los datos para procesarlos.

Recibir la imagen con PHP y guardarla en MySQL

Antes que nada: no soy un gurú de PHP, así que el código presentado a continuación no es necesariamente el más seguro, ni el más mantenible; por el contrario, es un código simple que explica el punto central del post.

Hecha la aclaratoria, veamos ahora el contenido del archivo de utilidades:

//Función auxiliar para errores (solo AJAX)
function mostrar_error($mensaje_error){
  $arr = array("error" => true, "mensaje" => $mensaje_error);
  echo json_encode($arr);
  exit();
};
//Conexión a la base de datos
function abrirConexion(){
  $db_host = '127.0.0.1'; //La dirección del servidor de BD
  $db_user = 'mi-usuario-mysql';
  $db_pw = 'mi-contrasena-mysql';
  $db_name = 'mi-base-de-datos-mysql';
  $connection = mysqli_connect($db_host, $db_user, $db_pw, $db_name);
  if (!$connection) {
    mostrar_error("No se puede conectar al servidor\\base de datos: $db_host\\$db_name");
  }
  return $connection;
}


Este script es bastante simple: una función encargada de generar una respuesta JSON en caso de un error (un error «controlado») para ser recibida por las llamadas a $.ajax(). La otra función se encarga de abrir la conexión a la base de datos usando la extensión de PHP MySQLi (NOTA: fíjate que no estoy usando la extensión tradicional MySQL, sino mysqli; tienen casi las mismas funciones pero la sintaxis es distinta). Para el ejemplo solo programé el mínimo código necesario para abrir la conexión y manejar errores, incluso coloqué las credenciales de la base de datos directamente en el script; queda de tu parte programar la conexión a la base de datos siguiendo procedimientos más seguros.

Este archivo de utilidades será incluido en el segundo script, mostrado a continuación:

include_once 'utilidades.php';
//Leemos los datos del usuario
$id = $_POST["id"];
$nombre = $_POST["nombre"];
//NOTA: La imagen viene en Base 64 (porque así la enviamos desde consultar.html)
$img = $_POST["imagen"];
//Abrimos una conexión a la base de datos
$conexion = abrirConexion();
//escapamos antes de armar la consulta
$id = mysqli_escape_string($conexion, $id);
$nombre = mysqli_escape_string($conexion, $nombre);
$img = mysqli_escape_string($conexion, $img);
//Si el usuario no existe lo insertamos,
//y si ya existe lo actualizamos
$consulta_sql = "INSERT INTO usuarios(id, imagen, nombre)\n".
                "    VALUES ('$id', '$img', '$nombre')\n".
                "ON DUPLICATE KEY\n".
                "    UPDATE imagen = VALUES(imagen), nombre=VALUES(nombre);";
mysqli_query($conexion, $consulta_sql)
    or mostrar_error("Error al ejecutar la consulta:\n$consulta_sql.\n\n".
                      mysqli_errno($connection) . ": " . mysqli_error($connection));
//La respuesta en formato JSON...
$respuesta = array(
    'ok' => true
);
echo json_encode($respuesta);

Este script recibe tres parámetros POST, enviados vía AJAX; los primeros dos son un ID (entero) que puede pertenecer a un usuario nuevo o existente, y el nombre del usuario. Por simplicidad omití la validación del ID (que debe ser un entero), pero al menos me aseguré de usar mysqli_escape_string() para evitar un ataque con código malicioso.

De momento no sabemos si el ID enviado pertenece a un usuario existente o a uno nuevo (esto fue intencional: recuerda que es un ejemplo simple de guardado); por esta razón usaremos INSERT... ON DUPLICATE: éste, intentará hacer el INSERT del nuevo registro, pero si éste falla por alguna restricción de clave única entonces ejecutará un UPDATE sobre ese mismo registro.

Si la consulta se ejecuta sin error el script termina enviando una respuesta positiva, en formato JSON, a la llamada AJAX que hicimos con javascript.

Y… ¿La estructura de la tabla?

No, no lo olvidé, veamos la estructura de la tabla para nuestros usuarios.

El siguiente script creará una tabla simple, con solo tres campos, para almacenar los registros:

CREATE TABLE 'usuarios' (
 'id' int(10) unsigned NOT NULL AUTO_INCREMENT,
 'imagen' blob NOT NULL,
 'nombre' varchar(50) CHARACTER SET latin1 COLLATE latin1_spanish_ci NOT NULL,
 UNIQUE KEY 'id' ('id')
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Para almacenar la imagen en el ejercicio de ejemplo escogí el tipo de datos blob. Este tiene una capacidad máxima de 2^16 bytes, unos 64Kb. Si necesitas más espacio puedes utilizar los otros tipos de blob, como mediumblob (2^24 bytes) o longblob (2^32 bytes), pero si necesitas tanto espacio probablemente debas reconsiderar si guardar las imágenes en base de datos o en disco 😉

¿Por qué BASE64 si ya tenemos la imagen en el fileinput?

Fíjate que en lugar de tomar la imagen directamente del fileinput, donde está en forma de archivo binario, la tomo del elemento img, donde está representada en formato BASE64 (en forma de texto, aproximadamente un 33% más pesado que el archivo original).

Para este ejercicio decidí enviar la imagen en BASE64 para almacenarla así mismo. Si revisas la vista previa con el inspector html de tu navegador, verás que las imágenes almacenadas como BASE64 se pueden insertar directamente en el atributo src de las imágenes. Si vas a incrustar la imagen frecuentemente en pdf, correo, o svg, podría ser más eficiente almacenarla de esta forma, ya que evitarás tener que pasarla de binario a BASE64 cada vez que lo necesites.

Pero si en cambio, frecuentemente vas a enviar al navegador la imagen como archivo «real», entonces tal vez te convenga guardarla en formato binario, justamente para evitar convertir desde BASE64 a binario cada vez. Claro, en este caso, tal vez sea incluso más eficiente guardar la imagen como archivo en una carpeta.

En todo caso quedará bajo tu responsabilidad seleccionar la opción de almacenamiento más eficiente; no, no hay normas establecidas, es como cuando entonas los índices de una base de datos, hay reglas generales sobre como hacerlo, pero al final debes analizar cada caso en particular.

Bueno, el artículo se extendió más de lo que esperaba, así que para la próxima la continuación: Leer imágenes desde MySQL con PHP.

Referencia

  • Extensión MySQLi para PHP: http://www.php.net/manual/en/mysqli.summary.php
  • Detalles sobre el tipo de datos Blob (y Text): http://dev.mysql.com/doc/refman/5.6/en/blob.html

Derecho de uso

Los contenidos generados por el autor de este artículo (explicaciones, código fuente, y archivos adjuntos creados por el autor) están disponibles bajo licencia CC BY-SA 3.0, y pueden ser usados, derivados y compartidos bajo los términos indicados en la misma. Los contenidos no generados por el autor de este artículo son propiedad de sus respectivos dueños y están regidos por las licencias que estos hayan dispuesto.

Cita del día

Improvement begins with I.
Arnold H. Glasow

, , , ,

33 respuestas a “Guardar Imágenes en MySQL con PHP”

  1. Hola muy buen aporte, podría pedirte un gran favor actualmente me encuentro haciendo un trabajo similar y sería de bastante ayuda si me guiaras con un ejemplo de como hacer un buscador de imagenes por nombre, de antemano muchas gracias

  2. Muchas gracias por responder y bueno si la idea es que dentro de una carpeta en la cual guardo la url pero tengo un campo llamado nombre y mediante un caja de texto realizar la busqueda y bueno he buscado ejemplos pero solamente hay de subirlos pero lo bueno de este dolor de cabeza es que se aprende bastante =d

    • OK, creo que entiendo lo que quieres: tienes una tabla con los nombres y urls de las imágenes, algo como:

      Nombre              Url
      **************************************
      Playa y mar         fotoplaya.jpg
      Niño con perro      animales01.jpg
      Montañas nubladas   naturaleza08.png
      Perros jugando      animales04.jpg
      **************************************
      

      Si es así, y en tu formulario el usuario escribe «perro» y presiona buscar, debes hacer una consulta (e.g. en MySQL):

      SELECT nombre, url FROM tabla_imagenes WHERE nombre LIKE '%perro%'
      

      Si la ejecutas desde PHP usando las funciones de MySQLi el resultado será un Array con los nombres y urls de las imágenes que «contienen» la palabra buscada por el usuario (en el ejemplo anterior devolvería 2 registros). Luego tienes que recorrer el array para enviar los nombres y urls a la pantalla (no sé si tu formulario lo harás para funcionar mediante un POST completo o usando AJAX).
      Si entendí lo que necesitas con esto tienes para empezar. Claro, la parte del LIKE es mejorable: podría modificarse para que el usuario pueda ingresar dos palabras y que los resultados busquen cualquiera de las dos (en lugar del texto exacto), usar comodines, etc.

      • amigo me enseñarias a crear un formulario de registro como por ejemplo nombre, aperridos, grado, email, y la foto, con php y myadminphp tambien nesecito que al momento de hacer una tabla dinamica donde me muestre los datos de la tabla usuarios me aparescan los datos nombre ,apellido,… y la foto.
        Lo nesecito con urgencia por favor puedes ayudarme

  3. Hola Roimer muchisimas gracias te comento para agradecerte por contestar mi gran duda, ahora te dejo un ejemplo de como realizo la búsqueda, te agradezco por tu ayuda

    Ingrese Nombre

    <input type="text" name="nom" value="» size=»20″>

    SELECT *
    FROM tablaImage
    WHERE Nombre LIKE ‘%».($_REQUEST[«nom»]).»%’
    ORDER BY IdImage desc»,$con);

    • De nada 🙂 solo un detalle más: tu código funciona, pero como regla general no debes concatenar valores tomados de una petición (con $_REQUEST, $_POST o similares) directamente con las consultas SQL, sino que debes «escaparlas» usando funciones como mysqli_escape_string() (como en el código de ejemplo de este artículo) o usando la clase PDO de PHP para protegerte contra un ataque de Inyección SQL.
      Por ejemplo, imagina que un usuario malicioso de tu web, o tu profesor revisando tu ejercicio, escribe en la caja de texto algo como:

      perro'; DELETE FROM tablaImage; --
      

      (texto + comilla simple + punto y coma + cualquier código SQL malicioso + punto y coma + dos guiones)
      ¡Te borraría todos los registros! o podría borrar toda la tabla con DROP TABLE, o toda la base de datos, o crear un nuevo usuario, etc… si quieres hacer la prueba intenta hacer un INSERT en lugar de un DELETE jejeje 😉

  4. Muy buen tutorial !!!. Bueno te posteo ya que tengo un gran problema, estoy intentando poder editar una imagen que se visualiza en el navegador, pero la edición en tiempo real, es decir que se pueda escribir encima de la imagen en cualquier posición y luego guardarla en una carpeta y además un nombre en un campo de la tabla de la BD. Esto lo he conseguido pero no he podido saber como editar imagenes que salgan en el navegador y tu puedas editarla en tiempo real.
    Me podrías ayudar ?? Un saludoo graciias!!
    Pienso que se hace con JQuery o ajax pero no se mucho de estos dos lenguajes. De verdad espero tu ayuda o guia.

    • Bueno Hackid1, tienes varias tareas para poder hacerlo, pero nada del otro mundo. Puedes usar jQuery por comodidad, aunque también lo puedes hacer «a mano», sería algo así:
      (1) Supongamos que comienzas por pedir al usuario que suba una imagen usando un input[type=file], esta imagen la «pintas» sobre un canvas. En este otro artículo hay un ejemplo para copiar una imagen desde un elemento video, pero es lo mismo copiarla desde un elemento image (mira la función en la sección «Captura de foto desde la cámara»).
      (2) El objeto Context del canvas (explicado brevemente en el link anterior) tiene funciones como drawImage, drawRectangle, strokeText (lista completa aquí )… con esto, puedes programar las funciones para que el usuario dibuje en en canvas «editando» la imagen que le acabas de pintar de fondo (y puedes «restaurarla» con solo volver a dibujar toda la imagen el canvas).
      (3) Una vez que el usuario termine de pintar en el canvas puedes tomar la imagen del mismo (usando el método toDataURL del objeto Context, la imagen estará en Base64, igual que al usar el método readAsDataURL en este artículo) y enviarla al servidor. A diferencia de este artículo, no guardarás la imagen en base de datos sino que la guardarás en una carpeta, usando las funciones file_put_contents() y base64_decode() de PHP (ejemplo en las primeras dos respuestas en esta pregunta de StackOverflow), por ejemplo.
      Bueno, con esto tienes para arrancar 🙂 Jejeje, creo que debería dedicarme a dar asesorías en programación 😛

  5. Muy buen tutorial gracias, me ayuda bastante aunque tengo una duda en la que espero puedas orientarme un poco mas, me encuentro realizando un sitio web donde de alta de productos e imágenes del mismo subidas por usuarios, la parte de los usuarios tanto registro como login ya lo tengo resuelto lo unico que no encuentro manera es en el producto e imagenes asociandolas al usuario correspondiente, si pudieras orientarme un poco porfavor.
    de antemano gracias!!

    • Hola Eduardo; según entiendo en tu web un usuario puede registrarse y «crear» un producto con una o más imágenes asociadas, así como en Mercado Libre donde para vender un artículo lo debes registrar y añadirle fotos para que otros las vean ¿Es correcto?
      Se me ocurre que cuando el usuario esté registrado y se haya logueado le muestres un formulario con la lista de artículos que tiene creado ese usuario y las imágenes asociadas al mismo; claro que la primera vez la lista estará vacía: el usuario llena los datos del artículo (nombre, descripción, detalles…) dentro de ese formulario o uno nuevo que salga cuando presione el botón «Nuevo Artículo…», el formulario para crear artículos tendrá uno (o más) input[type=file] para subir la imagen.
      Si la vas a guardar las imágenes en la base de datos podría ser dentro de un campo del mismo registro del artículo (podrían ser los campos imagen1, imagen2… imagen10 para permitir hasta 10 imágenes por artículo); pero si las vas a guardar en disco entonces en el registro del artículo guardarías el nombre (¡sin la ruta!) del archivo de la imagen, y en este caso tendrás que decidir entre dos opciones: (a) guardar todas las imágenes de todos los usuarios en la misma carpeta o (b) guardar las imágenes de cada usuario en una carpeta personal. Yo me iría por la misma carpeta para todos, pero recuerda no guardar las imágenes con el mismo nombre que el usuario le haya dado, sino que debes guardarlas con un nombre aleatorio generado por ti, no sea que dos usuarios suban una imagen con el mismo nombre y la sobre escribas.
      Me avisas si te sirve mi idea 🙂

  6. Hola buen día, sé que mi comentario no tiene que ver con el tema pero te agradecería muchísimo si me pudieras ayudar con este gran problema, no me sale la consulta del total de registros entre un rango de fechas, le he dejado el código que tengo hasta ahora, bueno desde ya muchas gracias.

    Servicios

    Desde: Hasta:

    Nombre
    Fecha
    Prueba

    prepare(«SELECT * FROM consulta WHERE fecha BETWEEN :a AND :b»);
    $result->bindParam(‘:a’, $d1);
    $result->bindParam(‘:b’, $d2);
    $result->execute();
    for($i=0; $row = $result->fetch(); $i++){
    ?>

    <?php

    $start_ts = strtotime($d1); // start time stamp
    $end_ts = strtotime($d2); // end time stamp
    $day_sec = 86400;
    $interval = ($end_ts – $start_ts)/$day_sec; // number of days
    echo "el rango es de $interval días\n»;
    $count = 0;
    $working_ts = $start_ts;
    while ($working_ts < $end_ts) { // loop through each day to find saturdays
    $day = date('Sa', $working_ts);
    if ($day == 7) { // this is a saturday
    $count++;
    }
    $working_ts = $working_ts + $day_sec;
    }
    echo "Hay $count Sabados en este intervalo\n»;

    $querys= mysql_query(«select count(*) from consulta where fecha between $start_ts AND $end_ts»);
    $total = mysql_num_rows($querys);
    echo ($total);
    }
    ?>
    prepare(«SELECT * FROM consulta WHERE fecha BETWEEN :a AND :b»);
    $result->bindParam(‘:a’, $d1);
    $result->bindParam(‘:b’, $d2);
    $result->execute();
    $numero = mysql_num_rows($result); // obtenemos el número de filas
    echo ‘El Toral de registros de la consulta es: ‘.$numero.»; // imprimos en pantalla el número generado

    $query = mysql_query(«select * from consulta»);
    $no_rows = mysql_num_rows($query);
    echo ‘El número de registros es: ‘.$no_rows.»;

    $query1=»select count(fecha) from consulta where fecha between :a AND :b»;
    $total_count = mysql_num_rows($query1);
    echo $total_count;
    ?>

    • Hola Juan Carlos, por lo que te entiendo, la parte de la consulta que te falla es donde cuentas los registros entre dos fechas:

      $start_ts = strtotime($d1); // start time stamp
      $end_ts = strtotime($d2); // end time stamp
      //más código aquí... 
      $querys= mysql_query("select count(*) from consulta where fecha between $start_ts AND $end_ts");
      

      Si es allí el problema, debe ser por que estás concatenando las variables de tipo fecha directamente en la consulta: no puedes hacer eso, ya que la fecha será convertida en cadena según la configuración de PHP (por ejemplo: «Sunday Jun 1st, 2014 12:30pm») y tu base de datos (MySQL?) no podrá parsearlo. Tienes que usar bindParam como en la primera consulta.
      Además, en la línea que dice echo ‘El Toral de registros de la consulta es: ‘.$numero.”; tienes un error de sintaxis: hay un punto y comilla doble de más al final.
      Un consejo: actualmente, por razones de seguridad, se desaconseja usar las funciones como mysql_query, y se prefiere usar funciones más «seguras» como mysqli_query (fíjate que le añade una «i» al nombre) o PDO::query().
      Comenta de nuevo si logras resolver, o si tienes alguna duda, trataré de responder más rápido 🙂

  7. Hola, jeje muchas gracias por responder y bueno decidí tratar con este otro código utilizando mysqli_query como mencionas y bueno he llegado hasta aquí en donde me muestra bien las consultas del rango y por ejemplo así sean los registros 2, 5, 8… me imprime «El total de registros son: 1″…. dependiendo del numero de registros que sean del rango en lugar de que imprima solo el numero, no se si me explique bien jeje espero pudieras ayudarme, muchas gracias (:

    Servicios Medicos

    Desde : Hasta:

    Nombre
    Fecha
    Prueba

    prepare(«SELECT * FROM consulta WHERE fecha BETWEEN :a AND :b»);
    $result->bindParam(‘:a’, $d1);
    $result->bindParam(‘:b’, $d2);
    $result->execute();
    for($i=0; $row = $result->fetch(); $i++){

    # comprueba si ha habido resultados, caso de no haberlos produce un mensaja de aviso
    //esta es la sentencia MySQL
    //$sentenciaMYSQL=»select count(*) from consulta where fecha between :a AND :b»;

    $mysql = new mysqli(«localhost»,»root», «», «serviciosmedicos»);

    $query = $mysql->prepare(«SELECT count(fecha) FROM consulta WHERE fecha BETWEEN $d1 AND $d2»);
    $query->execute();
    $query->store_result();

    $rows = $query->num_rows;

    echo «El total de registros son: $rows»;

    // Return 4 for example

    ?>

    • OK, ya veo el problema, no es nada grave 🙂 si ejecutas tu consulta directamente en MySQL (por ejemplo, desde PhpMyAdmin) lo verás:

      SELECT count(fecha) AS cantidad
      FROM consulta
      -- WHERE cualquier condicion
      

      Esto SIEMPRE devolverá una fila (por eso $query->num_rows siempre devuelve 1). Lo que debes hacer es leer el campo cantidad (yo agregué el AS cantidad a la consulta) de ese único renglón en lugar de contar las filas:

      $query = $mysql->prepare(“SELECT count(fecha) AS cantidad ".
                                  "FROM consulta ".
                                  "WHERE fecha BETWEEN $d1 AND $d2″);
      $query->execute();
      $query->store_result();
      //Obtiene la primera (y única) fila como Array Asociativo
      $row = $query->fetch_row(); 
      //Obtiene el valor del campo "cantidad" de la fila seleccionada
      $rows = $row["cantidad"]; 
      echo “El total de registros son: $rows”;
      
  8. Hola en verdad muchas gracias por las molestias y si entiedo lo del AS, y lo de contar cantidad, pero al usar el código que me proporcionas me marca el sig. error: Fatal error: Call to undefined method mysqli_stmt::fetch_now(), en la línea $row = $query->fetch_row(); por lo que intente utilizando mysqli_stmt_fetch y nada, opté por ocultarla :p
    pero funciona igual que antes se imprime El total de registros son:, El total de registros son: El total de registros son…
    no se que siga estando mal 🙁

    Servicios Medicos

    Desde : Hasta:

    Nombre
    Fecha
    Prueba

    prepare(«SELECT * FROM consulta WHERE fecha BETWEEN :a AND :b»);
    $result->bindParam(‘:a’, $d1);
    $result->bindParam(‘:b’, $d2);
    $result->execute();
    $rows = $result->num_rows;
    echo $rows;

    for($i=0; $row = $result->fetch(); $i++){

    $mysql = new mysqli(«localhost»,»root», «», «serviciosmedicos»);

    $query = $mysql->prepare(«SELECT count(fecha) AS cantidad FROM consulta «.
    «WHERE fecha BETWEEN $d1 AND $d2»);
    $query->execute();
    $query->store_result();
    //Obtiene la primera (y única) fila como Array Asociativo
    //$row = $query->fetch_now();
    //Obtiene el valor del campo «cantidad» de la fila seleccionada
    $rows = $row[«cantidad»];
    echo «El total de registros son: $rows»;
    ?>

  9. Hola me gustaría saber si tienes un ejemplo para guardar un documento pdf en una base de datos en Mysql usando PHP, poder visualizar este documento.

    • Hola Fidel,
      1) Puedes colocar varios input tipo texto, o uno solo con el atributo múltiple: con esto ya el usuario podrá seleccionar varias imágenes.
      2) Para la vista previa tendrás que crear un canvas para cada archivo seleccionado; para esto: revisas cada input a ver si tiene una imagen, o si usas uno múltiple recorres la colección Files con un bucle.
      3) Para el envío (si vas a usar AJAX como en el articulo) debes crear enviar un parámetro por cada imagen. Por ejemplo: coloca hasta 5, 10, 20… parámetros (tiene que haber un tope) y deja vacíos los que no vayas a usar.
      4) Para guardar: si planeas permitir pocas imágenes (e.g. màximo 3) podrías colocarlas en tres campos distindos de la misma tabla (en mi ejemplo: en los campos imagen1, imagen2 e imagen3 ed la tabla usuarios); pero si serán generalmente varias imágenes será mejor crear un registro para cada imagen en una tabla separada y asociarlos a la tabla principal mediante una clave.
      Toma en cuenta que si vas a subir muchas imágenes puede ser preferible que las guardes en disco en lugar de guardarlas en base de datos.

      • <?php
        require_once("settings.php"); //Load the settings
        $alert = ""; //Alert message after actions
        // Upload action
        if(isset($_FILES['file'])) {
        $extension = pathinfo($_FILES['file']['name']);
        $extension = $extension["extension"];
        $allowed_paths = explode(", ", $allowed_ext); //if any file is uploaded loads the allowed_ext from settings.php and explode the array
        $valid = 0;
        for($i = 0; $i < count($allowed_paths); $i++) {
        if ($allowed_paths[$i] == "$extension") {
        $valid = 1; // valid = 1 only if the extension is allowed in "settings.php" file
        }
        }
        if ($valid == 1 && $_FILES["file"]["size"] <= $max_weight) {
        if (file_exists("upload/" . $_FILES["file"]["name"])) {
        $alert = '’ . $_FILES[«file»][«name»] . ‘ La foto que introdujo ya existe ¡’ . ”; //the file already exists
        } else {
        move_uploaded_file($_FILES[«file»][«tmp_name»], “upload/” . $_FILES[«file»][«name»]);
        $save = $_FILES[«file»][«name»]; //It stores the name of the file in a variable
        $mysql = mysql_connect($db_host, $db_user, $db_password);
        mysql_select_db($db_name, $mysql);
        $sql = “INSERT INTO $table_name (Coctel, Ingredientes, Preparacion, File) VALUES (‘$_POST[Coctel]‘,’$_POST[Ingredientes]‘,’$_POST[Preparacion]‘,’upload/$save’)”; //stores records in database
        mysql_query($sql, $mysql);
        //$alert = ” . ‘Registro guardado exitosamente ¡’ . ”;
        $alert = ” . ‘Registro guardado exitosamente ¡’ . ”;
        //Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
        mysql_close($mysql);
        }
        } else {
        $alert = ” . ‘Registro no guardado ¡’ . ”; //the extension is not supported or the wight file is too big
        }
        }
        ?>
        body {
        background-image: url(deco/header-bg.jpg);
        background-repeat: repeat;
        }
        body,td,th {
        color: #F0F0F0;
        }
        function validarForm(formulario) {
        if(formulario.Coctel.value.length==0) { //comprueba que no esté vacío
        formulario.Coctel.focus();
        alert(‘Nombre del Coctel Obligatorio.’);
        return false; //devolvemos el foco
        }
        if(formulario.Ingredientes.value.length==0) { //comprueba que no esté vacío
        formulario.Ingredientes.focus();
        alert(‘Ingredientes del Coctel Obligatorio.’);
        return false;
        }
        if(formulario.Preparacion.value.length==0) { //comprueba que no esté vacío
        formulario.Preparacion.focus();
        alert(‘Preparación del Coctel Obligatorio.’);
        return false;
        }
        if(formulario.file.value.length==0) { //comprueba que no esté vacío
        formulario.file.focus();
        alert(‘Debe adjuntar una Foto del Coctel.’);
        return false;
        }
        return true;
        }
        function refresh()
        {
        document.location.reload();
        return false;
        }
        document.oncontextmenu = refresh;
        Altas de Cócteles
        body {
        background-image: url(deco/header-bg.jpg);
        }

        Solo imágenes jpg, jpeg, png. Máximo 300 Kb
        Limpiar Formulario

        Ver Resultado Modo 1
        Ver Resultado Modo 2
        ————————————————————————–
        Este es el código alguien puede ayudarme?
        Todo funciona bien, solo que me guarda solo una imagen.
        Saludos y gracias
        Este código es de este scripts pero viene preparado solo para una imagen
        datafile-upload-and-management-source

  10. datafile-upload-and-management-source (El código es de este Script)
    Solo que esta hecho para una imagen y yo quisiera para varias, si alguien puede ayudarme.
    Saludos y Gracias Fidel ( con una funciona muy bien)
    <?php
    require_once("settings.php"); //Load the settings
    $alert = ""; //Alert message after actions
    // Upload action
    if(isset($_FILES['file'])) {
    $extension = pathinfo($_FILES['file']['name']);
    $extension = $extension["extension"];
    $allowed_paths = explode(", ", $allowed_ext); //if any file is uploaded loads the allowed_ext from settings.php and explode the array
    $valid = 0;
    for($i = 0; $i < count($allowed_paths); $i++) {
    if ($allowed_paths[$i] == "$extension") {
    $valid = 1; // valid = 1 only if the extension is allowed in "settings.php" file
    }
    }
    if ($valid == 1 && $_FILES["file"]["size"] <= $max_weight) {
    if (file_exists("upload/" . $_FILES["file"]["name"])) {
    $alert = '’ . $_FILES[«file»][«name»] . ‘ La foto que introdujo ya existe ¡’ . ”; //the file already exists
    } else {
    move_uploaded_file($_FILES[«file»][«tmp_name»], “upload/” . $_FILES[«file»][«name»]);
    $save = $_FILES[«file»][«name»]; //It stores the name of the file in a variable
    $mysql = mysql_connect($db_host, $db_user, $db_password);
    mysql_select_db($db_name, $mysql);
    $sql = “INSERT INTO $table_name (Coctel, Ingredientes, Preparacion, File) VALUES (‘$_POST[Coctel]‘,’$_POST[Ingredientes]‘,’$_POST[Preparacion]‘,’upload/$save’)”; //stores records in database
    mysql_query($sql, $mysql);
    //$alert = ” . ‘Registro guardado exitosamente ¡’ . ”;
    $alert = ” . ‘Registro guardado exitosamente ¡’ . ”;
    //Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
    mysql_close($mysql);
    }
    } else {
    $alert = ” . ‘Registro no guardado ¡’ . ”; //the extension is not supported or the wight file is too big
    }
    }
    ?>
    body {
    background-image: url(deco/header-bg.jpg);
    background-repeat: repeat;
    }
    body,td,th {
    color: #F0F0F0;
    }
    function validarForm(formulario) {
    if(formulario.Coctel.value.length==0) { //comprueba que no esté vacío
    formulario.Coctel.focus();
    alert(‘Nombre del Coctel Obligatorio.’);
    return false; //devolvemos el foco
    }
    if(formulario.Ingredientes.value.length==0) { //comprueba que no esté vacío
    formulario.Ingredientes.focus();
    alert(‘Ingredientes del Coctel Obligatorio.’);
    return false;
    }
    if(formulario.Preparacion.value.length==0) { //comprueba que no esté vacío
    formulario.Preparacion.focus();
    alert(‘Preparación del Coctel Obligatorio.’);
    return false;
    }
    if(formulario.file.value.length==0) { //comprueba que no esté vacío
    formulario.file.focus();
    alert(‘Debe adjuntar una Foto del Coctel.’);
    return false;
    }
    return true;
    }
    function refresh()
    {
    document.location.reload();
    return false;
    }
    document.oncontextmenu = refresh;
    Altas de Cócteles
    body {
    background-image: url(deco/header-bg.jpg);
    }
     
     

    Solo imágenes jpg, jpeg, png. Máximo 300 Kb
    Limpiar Formulario

    Ver Resultado Modo 1
    Ver Resultado Modo 2
    Solo que esta hecho para una imagen y yo quisiera para varias, si alguien puede ayudarme.
    Saludos y Gracias Fidel

  11. EL EJEMPLO LO SUBI EN UN HOSTING DE PRUEBAS PERO NO SE SI SE DEBA A ALGUNA RESTRICCIÓN DEL HOSTING PERO SI ME PUDIERAS AYUDAR A RESOLVER MI PROBLEMA TE LO AGRADECERÍA.

  12. ola una pregunta yo estoy manejando un sistema en la que tengo que actualizar unos datos, el caso es el siguiente:

    mmm, mis datos ya se pueden actualizar y todo, pero la cosa esta asi, en la actualizacion tambien se require actualizar una imagen, si me actualiza pero… y si yo no quiero actualizar la imagen??? como le hago para que al momento de actualizar mis datos no sea necesario tambien actualizar la imagen, bueno, al menos que yo requiera hacerlo,???,
    xfavor, alguien responda!!!! P.D. manejo el php basico, nada de java u otra cosa!!!
    gracias!!!

  13. este es mi codigo, por si necesitan checarlo:)
    query($consulta);
    if($result){
    echo «Los datos han sido actualizados.»;
    copy(@$_FILES[‘fotografias’][‘tmp_name’], @$ruta);
    }else{
    echo «Error, intente de nuevo!!!»;
    }
    }

    @$id_clave=$_POST[‘id_clave’];
    @$consulta=»select * from personal where id_clave=’$id_clave’»;
    @$result=$db->query($consulta);
    @$num_result=$result->num_rows;
    @$row=$result->fetch_assoc();

    ?>

  14. Hola Roimer,

    Tu código no me funciona. Estoy revisando el artículo inicial, no los demás comentarios/solicitudes.

    Basicamente cargo la imagen inicialmente, y la visualizo sin problema. Pero cuando hago click en «Actualizar usuario», recibo un mensaje de error:
    Notice: Undefined index: imagen in RUTA\guardar_imagen.php on line 8

    Revise el contenido de «imagen», e hice un pequeño cambio:
    var parametros = {
    id : jQuery(‘#idUsuario’).val(),
    nombre : jQuery(‘#nombreUsuario’).val(),
    imagen : jQuery(‘#seleccionarImagen’).attr(‘src’)
    };
    $.ajax(‘guardar_imagen.php’, {

    en tu código en vez de #seleccionarImagen decia #temporal. Pero aún así no funciona…

    Estoy utilizando jquery 1.8 desde:
    http://code.jquery.com/jquery-1.8.0.min.js

    Agradezco tu valiosa colaboración.
    Juan Carlos

  15. Interesante el artículo, pregunta … ¿Y el paso inverso? Es decir tengo una imágen ya cargada en mysql y quiero guardarlo en el servidor , o más aún usar librerías como PHPExcel para exportarla en un archivo Excel. Te agradecería me puedas ayudar con eso.

    Gracias.

Soluciones claras y simples



Ing. Industrial, dedicado a la programación en ASP.NET+VB, SQL y Javascript+AJAX; y un poco de Android, Kotling, y Unity 🙂
Valencia, Venezuela



¿QUIERES APOYARME?

¿Te ha sido de ayuda alguno de mis artículos? Generar contenido técnico requiere de tiempo y esfuerzo. Con tu colaboración me puedes ayudar a mantener mi blog activo y actualizado. Si quieres y puedes apoyarme has clic aquí:

https://paypal.me/roimergarcia


ENTRADAS RECIENTES