importar archivo csv con PHP

Importar un archivo csv con PHP

En este artículo, te voy a explicar como hacer para importar un archivo csv con PHP dentro de una base de datos. Lo haremos usando la función fgetscsv de PHP y te contaré como funciona.

Y por ultimo, te dejaré un ejemplo completo, listo para descargar y usar con todos los archivos necesarios, incluida la estructura de la base de datos. Con todos los pasos comentados.

Para poder rellenar una tabla con los valores del archivo separado por comas (csv), tenemos que comenzar por la estructura de la base de datos.

Base de datos a rellenar con el archivo csv

Para este ejemplo, vamos a rellenar una tabla llamada comercios con los datos contenidos en un archivo de valores separados por coma, llamado comercios.csv

Así que lo primero es crear la tabla en la base de datos:

--
-- Estructura de tabla para la tabla `comercios`
--

CREATE TABLE `comercios` (
  `id_comercio` int(11) NOT NULL,
  `nombre` varchar(100) CHARACTER SET utf8 COLLATE utf8_spanish2_ci NOT NULL,
  `domicilio` varchar(200) CHARACTER SET utf8 COLLATE utf8_spanish2_ci NOT NULL,
  `telefono` varchar(50) CHARACTER SET utf8 COLLATE utf8_spanish2_ci NOT NULL,
  `codigo` int(5) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ALTER TABLE `comercios`
  ADD PRIMARY KEY (`id_comercio`);

ALTER TABLE `comercios`
  MODIFY `id_comercio` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;

Abrir la conexión con la base de datos

Para esto vamos a incorporar un archivo llamado conectar.php desde donde vamos a establecer la conexión con la base de datos y validar el acceso a la misma.

En este caso, fijate que en la linea donde definimos la conexión, tienes que reemplazar los datos con las credenciales de tu base de datos. En mi caso uso root como usuario y la base de datos se llama import_csv

//Configuracion
$conexion = new mysqli('localhost', 'root', '', 'import_csv');

//Conectar a la base de datos
if (mysqli_connect_errno()) {
    // La conexión falló. ¿Que vamos a hacer? 

    // Probemos esto:
    echo "Lo sentimos, este sitio web está experimentando problemas.<br>";

    // Algo que no se debería de hacer en un sitio público, aunque este ejemplo lo mostrará
    // de todas formas, es imprimir información relacionada con errores de MySQL -- se podría registrar
    echo "Error: Fallo al conectarse a MySQL debido a: <br>";
    echo "Num.Error: " . mysqli_connect_errno() . "<br>";
    echo "DescError: " . mysqli_connect_error() . "<br>";
    
    // Podría ser conveniente mostrar algo interesante, aunque nosotros simplemente saldremos
    exit;
}

El archivo con el formulario de subida

Voy a crear dos archivos: index.php e import.php. El archivo index.php contiene el código que es responsable de mostrar el formulario de carga de archivos. Y también de listar el contenido de la base de datos.

importar un archivo csv con PHP

Por otro lado, el archivo import.php es responsable de procesar el archivo csv, recorrer cada línea y almacenar los datos en la tabla comercios como veremos continuación.

Procesar el archivo separado por comas

Dentro del archivo import.php vamos a preparar una lista, con todos los tipos de archivos validos que se pueden aceptar. Y luego validamos si el archivo recibido esta dentro de esa lista.

$file_mimes = array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'application/x-csv', 'text/x-csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel', 'text/plain');

Abrir el archivo con fopen()

Una vez que validamos que el tipo de archivo, esta dentro de la lista de los formatos permitidos, vamos a abrirlo con la función fopen() para poder recorrer cada línea.

$csv_file = fopen($_FILES['file']['tmp_name'], 'r');

Recorrer los elementos del archivo usando la función fgetcsv()

Vamos a recorrer el archivo iterando con un While y por cada línea hacemos algunas verificaciones.

Si el comercio ya existe en la base de datos, lo actualizo, si no existe lo incorporo. En ambos casos, usaremos dos variables ($insertados y $actualizados) donde iremos almacenando la cantidad de movimientos.

 while (($comercio_registro = fgetcsv($csv_file)) !== FALSE) {

                // Convertir los acentos y caracteres especiales del nombre y domicilio
                $nombre = mb_convert_encoding($comercio_registro[1], 'UTF-8', 'ISO-8859-1'); 
                $nombre = $conexion -> real_escape_string($nombre); 
                $domicilio = mb_convert_encoding($comercio_registro[2], 'UTF-8', 'ISO-8859-1'); 
                $domicilio = $conexion -> real_escape_string($domicilio);

                // Verificar si ya existe el comercio
                $sql_query = "SELECT id_comercio, codigo FROM comercios WHERE codigo = '" . $comercio_registro[4] . "'";
                $resultset = mysqli_query($conexion, $sql_query) or die("database error:" . mysqli_error($conexion));

                // Si el comercio ya existe actualizo los datos, sino inserto el registro
                if (mysqli_num_rows($resultset)) {

                    $sql_update = "UPDATE comercios set nombre='" . $nombre . "', domicilio='"  . $domicilio . "', telefono='" . $comercio_registro[3] . "' WHERE  codigo = '" . $comercio_registro[4] . "'";
                    mysqli_query($conexion, $sql_update) or die("database error:" . mysqli_error($conexion));
                    $actualizados++;

                } else {

                    $mysql_insert = "INSERT INTO comercios (nombre, domicilio, telefono, codigo )VALUES('" .  $nombre . "', '" . $domicilio . "', '" . $comercio_registro[3] . "', '" . $comercio_registro[4] . "')";
                    mysqli_query($conexion, $mysql_insert) or die("database error:" . mysqli_error($conexion));
                    $insertados++;
                }
            }
            fclose($csv_file);

Mostrar los registros incorporados

Al final del archivo import.php, una vez que terminamos de recorrer cada una de las líneas, vamos a poder almacenar en las variables de sesión el resultado de todo el proceso.

Y serán esos valores los que vamos a consultar en el archivo index.php, para poder mostrar el resultado del proceso según los datos almacenados. Por ejemplo, si la variable de sesión message trae un valor success, mostramos el mensaje de éxito y la cantidad de registros insertados y modificados.

            // Almaceno los resultados en la variable de SESISON para mostrar los mensajes
            $_SESSION['message'] = "success";
            $_SESSION['insertados'] = $insertados;
            $_SESSION['actualizados'] = $actualizados;
        } else {
            $_SESSION['message'] = 'error';
        }
    } else {
        $_SESSION['message'] = 'invalid_file';

Manejo de los mensajes

Aparte de eso, hemos generado un mensaje en la parte superior del formulario. Este mensaje mostrará el estado de la carga en diferentes colores, según el tipo de resultado (success, error, invalid_file) y la cantidad de registros procesados.

Conclusión

Hoy te expliqué, en detalle, como hacer un script para importar un archivo csv con PHP. Repasando las líneas mas importantes del formulario y la lógica de carga.

Finalmente, aprovecho para compartir el ejemplo completo, listo para descargar y usar, desde mi repositorio de GitHub. Contiene todos los archivos mencionados en el post, la definición de la base de datos y el archivo comercios.csv, comentados en detalle para su mejor comprensión.

Todo el ejemplo está desarrollado sobre mi plantilla básica en HTML que compartí hace unas semanas. Lista para comenzar a modificar sin tener que lidiar con las configuraciones iniciales al momento de iniciar cualquier proyecto web.


Si te gustó o te entretuvo el contenido de este posteo, haciendo un click en los avisos me ayudas a mantener el sitio con vida y a seguir publicando.

Y si quieres ganar algo de dinero sin esfuerzo, registrate en Honeygain desde este banner y recibí 5 dolares de regalo al comenzar a usar la aplicación para generar ingresos pasivos.

HoneyGain

Acá puedes conocer más sobre ingresos pasivos, que es y como funciona HoneyGain.

Deja un comentario