PHP fgetcsv
Hoy veremos la función fgetcsv de PHP, como podemos ver en la página de PHP esta función hace lo siguiente: Obtiene una línea de un puntero a un fichero y la analiza en busca de campos CSV
Esta definición es un tanto engañosa, por ello fui a la versión en inglés:
Gets line from file pointer and parse for CSV fields
php.net -fgetcsv
Un pointer no es lo mismo que un file pointer aunque estan relacionados, en el siguiente link podrá leer sobre exactamente lo que es un file pointer https://docs.microsoft.com/en-us/windows/win32/fileio/file-pointers.
Vamos a poner esto más en blanco y la definición nos quedaría:
Obtiene una línea de un file pointer y la analiza en busca de campos CSV
Descriptionfgetcsv( resource $stream, ?int $length = null, string $separator = ",", string $enclosure = "\"", string $escape = "\\" ): array|falseSintaxis
fgetcsv($stream,$length,$separator,$enclosure,$escape)
Valores de la función
Parametros
$stream
– es un stream de datos obtenido después de usar fopen u otra función para abrir un archivo (popen(),fsockopen()) en realidad sería el puntero al archivo que se ha abierto.
ejemplo: $stream = fopen("mycsv.csv", "r"))
$length
– la longitud máxima que se espera de la línea obtenida del csv, esta línea serian las filas en una plantilla de Excel u otro programa similar. Este valor es opcional a partir de PHP 8.0, en caso de no especificar tomará el máximo valor posible.
$separator
-(opcional) indica el delimitador , en este caso ,
es el delimitador por defecto, ya que los csv utilizan la , para separar los distintos valores.
$enclosure
-(opcional) en este caso "
es el valor de enclosure, este es el valor con el que está cercado el campo
$escape
-(opcional) define el carácter de escape, en este caso es \
, si $escape
es igual a ""
deshabilita esta propiedad.
Valores de retorno
Retornará un array indexado en caso de éxito y false si no se ha podido obtener la línea que sigue.
Que es un CSV
Generalmente, se utilizan programas como Excel y otros similares para realizar distintos cálculos, funciones o incluso organizar información. Esta clase de programas nos permiten guardar como archivos csv.
Las siglas csv significan valores separados por coma y literalmente es lo que hacen por ejemplo si tenemos la siguiente tabla de excel:
producto | precio | stock |
percha | 50 | 20 |
almohada | 200 | 12 |
colcha | 511 | 2 |
pantuflas | 150 | 231 |
toalla belagio | 550 | 31 |
acolchado linea blanca | 3300 | 20 |
vela diseño | 208 | 22 |
Cuando guardemos el archivo como csv pasará a estar de esta manera
archivo.csvproducto,precio,stock percha,50,20 almohada,200,12 cocha,511,2 pantuflas,150,231 toalla belagio,550,31 acolchado línea blanca,3300,20 vela diseño,208,22
Ejemplo de uso de PHP fgetcsv
Empecemos viendo el ejemplo más simple que podemos con esta función e iremos viendo como todo tiene sentido.
Obteniendo la primera linea<?php if (($gestor = fopen("cvs.csv", "r")) !== FALSE) { if (($datos = fgetcsv($gestor, 1000, ",")) !== FALSE) var_dump($datos); } ?>
array(5) { [0]=> string(0) "" [1]=> string(0) "" [2]=> string(0) "" [3]=> string(0) "" [4]=> string(0) "" }
Ok que ha pasado aquí, ¿no estoy obteniendo datos? L o que ha pasado en este ejemplo es que nuestra tabla no empieza en la columna 0 – fila 0 y por ende está obteniendo los valores sin nada de la fila 0.
Cuando convertí mi archivo de Excel a CSV este paso las filas sin nada como ,,, y también las columnas ,,
Ahora veamos el ejemplo de tabla que vimos en Que es un CSV, pero esta vez empezando desde columna 0 y fila 0
ejemplo fgetcsv<?php if (($gestor = fopen("cvs.csv", "r")) !== FALSE) { while (($datos = fgetcsv($gestor, 1000, ",")) !== FALSE) { $numero = count($datos); for ($c=0; $c < $numero; $c++) { echo $datos[$c]; } echo "<br/>"; } fclose($gestor); } ?>
productopreciostock percha5020 almohada20012 colcha5112 pantuflas150231 toalla belagio55031 acolchado linea blanca330020 vela dise�o20822
Ejercicios:
Ejercicio 1
En los 2 ejemplos anteriores vimos que al guardar como CSV una tabla que no empieza en posición obtendremos información en blanco.
Crea una tabla en Excel en un lugar inapropiado y guarda esta en un archivo cvs.csv, al código visto en el ejemplo 2 modifícalo para que este depure la información para solo obtener los datos pertinentes.
Para poder realizar este ejercicio necesitarás un poco de investigación de tu parte.
Ejercicio 2
En el ejercicio anterior se pide que se devuelva los campos limpios sin los espacios innecesarios que nos da poner una tabla en un lugar inapropiado antes de exportarla como .csv.
Para ello debemos de tener en cuenta lo que hicimos en los 2 ejemplos anteriores.
En el ejemplo 1 vimos como obtener una fila de este .csv, mientras que en el ejemplo 2 recorrimos por completo este .csv
Como ve en el ejercicio, se pide un poco de investigación de nuestra parte: y de hecho es que necesitaremos de una función para rebobinar(rewind) a nuestro puntero a archivo.
Ejercicio 2 Resuelto
Veamos como sería nuestro ejercicio resuelto:
Nuestra parte principal[csv4.php]<?php $list=[]; $col=[]; if (($gestor = fopen("cvs.csv", "r")) !== FALSE) { //preset cols $data_analysis = fgetcsv($gestor, 1000, ","); $number = count($data_analysis); for ($n = 0 ; $n < $number; $n++) { $col[$n] = false; } rewind($gestor); //lines iteration while (($data = fgetcsv($gestor, 1000, ","))!==FALSE) { $not_empty = !checkRowEmptiness($number,$data); if($not_empty) $list[] = $data; } $depurated_list =[]; foreach ($list as $element) { $depurated_list[] = array_slice($element,sliceposition($col)); } var_dump($depurated_list); }
Como podemos ver desde el comentario //preset cols hasta el rewind hara que $col que son las columnas que tenemos en la tabla sean false por defecto.
Luego haremos un rewind, ya que deseo empezar desde el inicio a chequear todo esto.
En el siguiente while chequearemos si las líneas están vacías o no, de esta manera eliminaremos las filas que están totalmente vacías. Este array nuevo será $list[]
«» | «» | «» | «» | «» | «» |
«» | «» | «» | «» | «» | «» |
«» | «» | x | x | x | x |
«» | «» | x | x | x | x |
«» | «» | x | x | x | x |
«» | «» | x | x | x | x |
Como se veria el contenido de $list[] si fuera una tabla
«» | «» | x | x | x | x |
«» | «» | x | x | x | x |
«» | «» | x | x | x | x |
«» | «» | x | x | x | x |
Ahora deberemos depurar nuestras filas para no tener nuestras columnas vacías para eso utilizaremos el array_slice que nos dará un nuevo array a partir del anterior, el cual lo agregaremos a nuestra lista depurada $depurated_list[]
Por otra parte, tenemos nuestras funciones:
función checkRowEmptiness [csv4.php]/** * Check if the row is empty, in case its empty * @param $number * @param $data * * @return bool */ function checkRowEmptiness(int $number,array $data): bool{ global $col; for ($i=0; $i < $number; $i++) { if ($data[$i]!= "" ) { $col[$i] = true; return false; } } return true; }función sliceposition [csv4.php]
/** * Return slice position depending in column_emptiness after found first colum with data * @param $col * * @return int */ function sliceposition(array $col): int{ for ($i=0; $i<count($col); $i++) { if ($col[$i]== true) return $i; } }