Como hacer una galería de imágenes en PHP

Con PHP se puede hacer una galería de imágenes muy fácilmente y con un CSS le daremos un poco de estilo para que la galería sea más bonita y con lightbox mostraremos las imágenes.

El proceso para hacer la galería de imágenes se puede separar en dos apartados, subir las imágenes y mostrar las imágenes.

Como subir las imagenes para la galeria

Para subir las imágenes lo primero es crear un formulario para elegir las imágenes que se quieran subir. Vamos con ello.


<form action="#" method="POST" enctype="multipart/form-data">
    <table id="formularioSubida" border="0">
        <thead>
            <th>Elige los archivos que quieras subir</th>
        </thead>
        <tr>
            <td>
                <div class="inputImagenModificado">
                    <input class="inputImagenOculto" name="imagen1" type="file">
                    <div class="inputParaMostrar">
                        <input>
                        <img src="imagenes/button_select2.gif">
                    </div>
                </div>
            </td>
        </tr>
        <tr>
            <td> 
                <input type="button" id="botonAnnadir" onClick="agregarFila('formularioSubida','botonAnnadir')" value="Añadir archivo" style="width:138px;">        
                <input type="submit" name="botonSubir" value="Subir"> 
            </td>
        </tr>
    </table>
</form>

En el formulario anterior, he modificado el estilo del input file (mira aquí como), pero si no se quiere modificar se puede eliminar el div inputImagenModificado y sustituirla por un simple input file (<input class=»inputImagenOculto» name=»imagen1″ type=»file»>).

También en la línea 19, he puesto un botón para generar más input file dinámicamente para permitir subir varias imágenes a la vez si se quiere pero a la vez que la pagina no este llena de inputs.

Para generar los inputs usaremos una función JavaScript siguiente:


var numeroFila=2;

/*
 * Funcion que agrega un nueva fila a la tabla para subir imagenes, para poder subir mas de una.
 * 
 * @param idTabla Identificador de la tabla en la que se quiere añadir una nueva fila
 * @param idBoton Identificador del boton que llama a esta funcion
 */

function agregarFila(idTabla,idBoton){
    
    // Limitamos el numero de filas a 10.
    if (numeroFila <= 10){
        // Inserta una nueva fila en la posicion numeroFila (la ultima).
        nuevaFila = document.getElementById(idTabla).insertRow(numeroFila);
        
        nuevaCelda = nuevaFila.insertCell(-1);
        nuevaCelda.innerHTML = '<td><div class="inputImagenModificado"><input class="inputImagenOculto" name="imagen'+numeroFila+'" type="file"><div class="inputParaMostrar"><input><img src="imagenes/button_select2.gif"></div></div></td>';

        // Funcion para modificar el estilo de los inputs
        mostrarInputFileModificado('imagen'+numeroFila);
        
        // Incrementa numeroFila
        numeroFila ++;
    } else {
        // Inserta una nueva fila en la posicion numeroFila (la ultima).
        nuevaFila = document.getElementById(idTabla).insertRow(numeroFila);

        // Inserta una nueva celda en la fila nueva, en la ultima posicion (por el -1). 
        nuevaCelda = nuevaFila.insertCell(-1);
        nuevaCelda.innerHTML = '<td>Solo se pueden subir 10 archivos a la vez.</td>';
        
        // Desactivamos el boton para agregar mas filas.
        document.getElementById(idBoton).disabled = true;
    }
}

Con esta función generamos los campos dinámicamente, y la línea que lo hace es nuevaCelda.innerHTML =’…’; es con la que generaremos el contenido dinámicamente, por lo tanto con modificar el contenido de esta función podemos modificar el código HTML que se generara. La función limita el número de campos creados a 10 y deshabilita el botón para que no se puedan crear más campos. Nota: Cuando pruebes a subir archivos comprueba en el archivo php.ini que el tamaño de todos los archivos juntos sea menor que el especificado en post_max_size. Sino aumenta el tamaño máximo permitido que por defecto es muy bajo.

Con lo visto hasta el momento aun no se pueden subir las imágenes, es necesario crear una función para subir los archivos que seleccionamos con los input file.


/**
 * Funcion para subir imagenes
 * 
 * @param $campoArchivo Nombre del campo en el que se subira el archivo.
 * @param $dir Directorio en el que se guardara la imagen. 
 * @param $conexion Conexion con la base de datos.
 */

function subirImagen($archivo, $dir, $conexion){     
    // Se comprueba que el archivo a subir sea una imagen.
    if($_FILES[$archivo]["type"] == "image/jpeg"){
            
        // Se comprueba si ha ocurrido algun error al subir el archivo.
        if ($_FILES[$archivo]["error"]) {
            echo '<div class="error">Error '.$_FILES["archivo"]["error"].'al intentar subir el archivo '.$_FILES[$archivo]["name"].'</div>';
        } else {
            // Se comprueba si ya se ha creado el subdirectorio para almacenar la imagen.
            // Y se crea si no existe aun.
            if(!is_dir("imagenes/".$dir)){
                mkdir("imagenes/".$dir, 0755);
            }

            // Comprobamos que no haya ningun archivo con el mismo nombre en el servidor.
            if (file_exists("imagenes/".$dir."/".$_FILES[$archivo]["name"])) {
                echo '<div class="error">Ya hay un archivo con nombre '.$_FILES[$archivo]["name"].'. Renombralo y vuelve a subirlo.</div>';   
            } else {
                // Subimos la imagen.
                move_uploaded_file($_FILES[$archivo]["tmp_name"], "imagenes/".$dir."/".$_FILES[$archivo]["name"]);
                echo '<div class="subido">Archivo '.$_FILES[$archivo]["name"].' subido.</div>';
                                        
                // Agregamos la imagen a la base de datos.
                $consulta = sprintf("INSERT INTO galeriaimagenes (archivo, directorio) VALUES ('%s','%s')",          
                    $conexion->real_escape_string($_FILES[$archivo]["name"]),
                    $conexion->real_escape_string($dir)
                );
                    
                // Se ejecuta la consulta.
                $conexion->query($consulta);
            }
        }
    } else {
        echo '<div class="error">'.$_FILES[$archivo]["name"].': Formato de archivo no permitido. </div>';
    }      
}

La función esta comentada prácticamente línea por línea con lo que no creo que sea necesario añadir nada más, salvo de decir que se puesto la posibilidad de especificar el directorio en el que se quieren almacenar las imágenes para permitir que se puedan crear múltiples galerías, por ejemplo una por cada nombre de usuario. Y también que tanto el directorio como el nombre del archivo se almacenaran en una base de datos, para luego poder visualizarlas, se podría añadir una descripción u otros campos pero por simplificar la galería no se ha hecho, aunque es tan sencillo como añadir los inputs para almacenar la información que queramos añadir y luego añadirlo a la base de datos del mismo modo que se ha hecho con el nombre de la imagen o el directorio.

El código SQL para crear la tabla para almacenar las imágenes es el siguiente:


CREATE TABLE 'galeriaimagenes' (
  'id' int(3) NOT NULL AUTO_INCREMENT,
  'archivo' varchar(20) NOT NULL,
  'directorio' varchar(20) NOT NULL,
  PRIMARY KEY ('id')
);

Con la función anterior podemos subir las imágenes individualmente. Para simplificar el proceso de subir las imágenes crearemos otra función que subirá todas las imágenes, bueno realmente llamara a la función anterior con cada imagen haciendo que solo sea necesario incluir una llamada a esta función y no una llamada por cada imagen que se quisiese subir.


/**
 * Funcion que comprueba los input file que contienen algo y llama a la funcion encargada de subir las imagenes.
 * 
 * @param type $dir Directorio en el que se quiere subir las imagenes (usar '' si no se quiere usar un subdirectorio).
 * @param $conexion Conexion con la base de datos.
 */

function subirImagenes($dir, $conexion){
    // Recorremos la lista de campos para subir archivos.
    foreach ($_FILES  as $key =< $value) {
        // Se comprueba si el nombre del archivo no esta vacío para subirlo
        if ($_FILES[$key]["name"] != ''){
            subirImagen($key, $dir, $conexion);
        }
    }
}

Esta función recorre los imput files y comprueba que contengan algo y si es asi llama a la función que expliquemos anteriormente. Finalmente añadimos en el archivo en el que tenemos el formulario, detrás de este una llamada a esta función dentro de un if que comprueba si se ha pulsado el botón subir.


<?php
    // Subir todas las imagenes
    if(isset($_POST['botonSubir'])){
        subirImagenes('prueba',$conexion);
    }
?>

Ahora si, con lo hecho hasta el momento ya podemos subir las imágenes y solo queda el código necesario para mostrarlas como una galería.

Con esta sencilla línea basta para mostrar una imagen, y metiéndola dentro de un bucle que recorra todas las imágenes ya tendríamos la galería, aunque la verdad el resultado seria bastante malo pues se mostrarían todas las imágenes en su tamaño original.


echo '<img src="imagenes/'.$dir.'/'.$_FILES[$archivo]["name"].'">';

Este es el código con el que generaremos la galería, un simple bucle en el que se muestran las imágenes, enlazadas a si mismas para mostrarlas con lightbox. Cosa que se consigue con la etiqueta rel=»lightbox[loquequieras]» ([loquequieras] hace que las funciones de lightbox entiendan que las imágenes con esta etiqueta están relacionadas y por lo tanto añade los enlaces para moverse entre las imagenes). La etiqueta title=»» sirve para poner el nombre que se mostrara debajo de la imagen con lightbox.


<div class="galeria">
    <h1>Mis Imagenes</h1>
    <?php
        require 'config.php';

        $conexion = new mysqli($servidor, $usuarioBD, $passwordBD, $baseDatos);

        $consulta = "SELECT archivo, directorio FROM galeriaimagenes ORDER BY id";
        $resultado = $conexion->query($consulta);

        // Muestra las imagenes de la galeria.
        while($filas = $resultado->fetch_array(MYSQLI_ASSOC)) {
            // Se comprueba que existan las imagenes
            if (file_exists("imagenes/".$filas["directorio"]."/".$filas["archivo"])){
                echo'<a href="imagenes/'.$filas['directorio'].'/'.$filas['archivo'].'" rel="lightbox[galeria]" title="'.$filas['archivo'].'"><img src="imagenes/'.$filas['directorio'].'/'.$filas['archivo'].'"/></a>';
            }                    
        }
    ?>
</div>

Para usar ligthbox es necesario obviamente incluir los archivos que contienen las funciones y el estilo e incluir las siguientes referencias en el archivo donde queramos mostrar las imágenes:


<script type="text/javascript" src="lightbox/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="lightbox/js/jquery-ui-1.8.18.custom.min.js"></script>
<script type="text/javascript" src="lightbox/js/jquery.smooth-scroll.min.js"></script>
<script type="text/javascript" src="lightbox/js/lightbox.js"></script>
<link rel="stylesheet" href="lightbox/css/lightbox.css" type="text/css" />

Para el mejor aspecto de la galería realice unas pequeñas modificaciones en el codigo de los archivos lightbox.js y lightbox.css para limitar el tamaño en el que se muestran las imágenes. Estos archivos están incluidos junto con el resto del proyecto al final del post, si quieres los archivos originales puedes encontrarles aquí.

Y para darle a la galería un aspecto de galería basta con estas líneas de código CSS:


body {
    background: darkgrey; 
}

.galeria{
    width: 1080px;
    margin: auto;
    background: black;
    color: bisque;
    padding: 20px 10px 10px 20px;
    border-radius: 10px;
    box-shadow: 0 10px 10px 0 rgba(0, 0, 0, 0.6);    
}
.galeria img{
    width: 200px;
    height: 200px;
    border: 1px solid white;
    padding: 1px;
    margin-right: 10px;
    margin-bottom: 10px; 
    border: 2px solid bisque;
    border-radius: 5px;
}

Con esto hacemos que las imágenes se muestren con un tamaño uniforme de 200×200 con un borde y con esquinas redondeadas con lo que la galería queda bastante curiosa.

Y para finalizar le añadiremos mediante JavaScript un «sombreado» a las imágenes para que se muestren un poco oscuras y cuando se pase el ratón por encima de alguna se aclaren. Este efecto se consigue con una sencilla función que deje la opacidad de la imagen en 1 cuando se esta sobre ella y la modifique al valor que nosotros queramos cuando no. Por ejemplo 0,5.


/**
 * Cambia la opacidad de las imagenes de la galeria cuando no se esta sobre ellas al valor pasado como parametro.
 * 
 * @param opacidad Valor entre 0 y 1 que determinara la opacidad de la imagen.
 *  
 */

function cambiarOpacidadImagenes(opacidad) {
    $(document).ready(function(){
        // Pone la opacidad de las imagenes al porcentaje indicado en opacidad.
        $('.galeria img').animate({"opacity" : opacidad});

        // Al pasar el raton sobre la imagen (over) se ejecuta la primera funcion y al salirse la segunda (out).
        $('.galeria img').hover(
            function(){
                $(this).animate({"opacity" : 1});
            },
            function(){
                $(this).animate({"opacity" : opacidad});
            }
        );
    });
}

El resultado final es este:

Imagen con lightbox:

Inputs desplegados:

Con este código como puedes ver se puede conseguir una galería sencilla pero elegante, pero para que pudiese funcionar más fluida sería mejor añadir una función que crease las miniaturas de las imágenes para mostrarlas en la galería pero con las velocidades de hoy en día y suponiendo que no subas imágenes de unos cuantos megas prácticamente ni se notaria.

Si quieres ver el código completo puedes descargarlo aquí.