Dans un premier article nous avons vu comment transformer un tableau PHP et l’exporter en fichier CSV. Cet article est l’inverse, il va vous permettre de pouvoir générer un tableau PHP à partir d’un tableau CSV.
Nous allons donc transformer un fichier CSV de ce type :
first name | last name | phone | |
---|---|---|---|
Bastien | Malahieude | 06 XX XX XX XX XX | contact@bastienmalahieude.fr |
John | Doe | 06 XX XX XX XX XX | john@doe.fr |
et de récupérer un tableau PHP sous cette forme :
array(2) { [0]=> array(4) { ["first name"]=> string(7) "Bastien" ["last name"]=> string(10) "Malahieude" ["phone"]=> string(17) "06 XX XX XX XX XX" ["email"]=> string(28) "contact@bastienmalahieude.fr" } [1]=> array(4) { ["first name"]=> string(4) "John" ["last name"]=> string(3) "Doe" ["phone"]=> string(17) "06 XX XX XX XX XX" ["email"]=> string(11) "john@doe.fr" } }
Pour cela nous allons créer une fonction import_csv_to_array qui permet d’importer les données depuis un fichier et qui retourne un tableau PHP. Cette fonction prend deux paramètres dont un seul obligatoire :
- $file : Ce paramètre est le chemin vers le fichier.
- $enclosure : Le caractère qui entoure les chaînes de caractères.
function import_csv_to_array($file,$enclosure = '"') { // @TODO Do something here }
Dans un premier temps, nous allons récupérer le contenu du fichier via la fonction file_get_contents.
$csv_string = file_get_contents($file);
Ce contenu est stocké comme chaîne de caractères dans la variable $csv_string
Deviner le séparateur de caractères du fichier CSV
La plupart des programmes d’import de fichier CSV demandent à l’utilisateur de choisir quel est le délimiteur sur son fichier. En effet, les données dans un fichier CSV peuvent être délimités par plusieurs chaînes de caractères. Les plus courant sont le point-virgule (;) la virgule (,) ou la tabulation. Il arrive aussi dans de rares cas que les données soient délimitées par un pipe ( | ).
En fonction de la taille du fichier CSV, il est fort probable que le délimiteur utilisé soit le caractère de ces quatre qui est le plus présent au sein du fichier. Nous allons utiliser cette particularité afin de tenter de deviner le séparateur utilisé dans le fichier CSV, et ainsi de rendre la fonction compatible avec le plus de fichiers possibles.
Pour celà, nous allons tout d’abord créer un tableau avec les délimiteurs possibles. En fonction de votre projet vous pouvez en ajouter ou en retirer du tableau :
// List of delimiters that we will check for $delimiters = array(';' =>; 0,',' =>; 0,"t" =>; 0,"|" =>; 0);
Note : Si vous savez toujours quel délimiteur est utilisé dans vos fichier, cette étape est inutile.
Ensuite, nous allons entrer dans ce tableau, le nombre d’occurrences de chacun des délimiteurs, en comptant à l’aide de substr_count leur apparition dans le fichier
foreach ($delimiters as $delimiter => &$count) { $count = substr_count($csv_string,$delimiter); }
Utiliser &$count ici permet d’ajouter le résultat directement dans le tableau $delimiters. il équivaut à utiliser $delimiters[$delimiter]. Plus d’informations ici
Cette boucle nous permet alors de récupérer un tableau contenant le nombre d’occurrences de chacun des délimiteurs proposés, au sein de notre chaîne $csv_string.
La dernière étape est de récupérer dans le tableau la clé pour laquelle la valeur $count est la plus grande. Ici nous allons utiliser la fonction array_search ainsi que la fonction max
array_search(max($delimiters), $delimiters);
Récupération des données du fichier
La seconde étape de notre fonction est de récupérer toutes les données du fichier afin de les ajouter dans notre tableau PHP.
Pour ça, on va récupérer dans un tableau toutes les lignes du fichier CSV. Le séparateur de lignes étant une nouvelle ligne n on va utiliser la fonction explode.
$lines = explode("n", $csv_string);
Notre fichier CSV contient des en-têtes, ces en-têtes sont récupérés dans la première ligne. La fonction array_shift permet de récupérer la première ligne d’un tableau.
Ensuite, nous utilisons la fonction str_getcsv. Cette dernière permet de découper une ligne de fichier CSV dans un tableau PHP.
$head = str_getcsv(array_shift($lines),$delimiter,$enclosure);
Une fois les en-têtes récupérées, on va créer un tableau pour stocker nos données. Ensuite, on peut boucler sur toutes les autres lignes du tableau avec la procédure foreach
$array = array(); foreach ($lines as $line) { // Gestion ici des lignes }
Il arrive parfois que certains fichier disposent de la dernière ligne vide. Pour celà, on vérifie que les données existent bien dans notre ligne :
if(empty($line)) { continue; }
Si il y a des données, on va alors exporter le contenu de la ligne, de la même manière que pour les en-têtes ci-dessus :
$csv = str_getcsv($line,$delimiter,$enclosure);
Enfin, en utilsiant array_combine on va pouvoir ajouter les clés aux valeurs de chaque ligne que l’on a récupéré. Puis on peut ajouter le tout dans notre tableau de données $array :
$array[] = array_combine( $head, $csv );
Enfin, on retourne le tout :
return $array;
FONCTION PHP COMPLÈTE
Pour plus de lisibilité dans le code, j’ai décidé de découper la partie qui devine le séparateur du fichier CSV dans une seconde fonction dédiée.
La fonction finale que l’on vient de créer est la suivante :
/** * * This function allows you to import a CSV file and export it into a PHP array * * @param string $file The file you want to import the data from * @param string $enclosure The type of enclosure used in the CSV file * * @return array The array containing the CSV infos */ function import_csv_to_array($file,$enclosure = '"') { // Let's get the content of the file and store it in the string $csv_string = file_get_contents($file); // Let's detect what is the delimiter of the CSV file $delimiter = detect_delimiter($csv_string); // Get all the lines of the CSV string $lines = explode("n", $csv_string); // The first line of the CSV file is the headers that we will use as the keys $head = str_getcsv(array_shift($lines),$delimiter,$enclosure); $array = array(); // For all the lines within the CSV foreach ($lines as $line) { // Sometimes CSV files have an empty line at the end, we try not to add it in the array if(empty($line)) { continue; } // Get the CSV data of the line $csv = str_getcsv($line,$delimiter,$enclosure); // Combine the header and the lines data $array[] = array_combine( $head, $csv ); } // Returning the array return $array; } /** * * This function detects the delimiter inside the CSV file. * * It allows the function to work with different types of delimiters, ";", "," "t", or "|" * * * * @param string $csv_string The content of the CSV file * @return string The delimiter used in the CSV file */ function detect_delimiter($csv_string) { // List of delimiters that we will check for $delimiters = array(';' =>; 0,',' =>; 0,"t" =>; 0,"|" =>; 0); // For every delimiter, we count the number of time it can be found within the csv string foreach ($delimiters as $delimiter => &$count) { $count = substr_count($csv_string,$delimiter); } // The delimiter used is probably the one that has the more occurrence in the file return array_search(max($delimiters), $delimiters); }
Le code est disponible sur github dans le repository xusifob/lib
N’hésitez pas à laisser votre avis dans les commentaires ci-dessous !