Dans ce premier article de la série, nous allons essayez de créer une fonction afin d’exporter un tableau PHP en fichier CSV, lisible sous Excel.
Le but de la manipulation est d’avoir en données d’entrée un tableau associatif PHP et en sortie un fichier CSV qui sera téléchargé sur l’ordinateur de l’utilisateur. Pour cela, nous allons créer la fonction export_data_to_csv().
Nous allons donc transformer le tableau PHP suivant :
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" } }
En un fichier CSV comportant les données suivantes :
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 |
Notre fonction prendra 4 arguments afin de la rendre la plus modulable possible
- $data : Le tableau de données
- $filename : Le nom du fichier que l’on souhaite exporter
- $delimiter : Le délimiteur CSV que l’on souhaite utiliser. Par défaut “;” pour être compatible avec excel
- $enclosure : Le caractère qui permet de délimiter les chaînes de caractères. Par défaut le guillemet “
L’instanciation de notre fonction sera donc la suivante :
function export_data_to_csv($data,$filename='export',$delimiter = ';',$enclosure = '"') { //@TODO Do something here }
Export des données PHP au format CSV
La première étape est ensuite de forcer le navigateur à prendre en compte nos données comme un fichier CSV. Cela se fait au niveau des en-têtes http envoyées au client.
// Dit au navigateur que les données retournées sont un fichier qui s'appelle $filename.csv header("Content-disposition: attachment; filename=$filename.csv"); // Dit au navigateur que les données retournées sont un fichier csv. header("Content-Type: text/csv");
Ecriture dans le fichier
Puisque l’on souhaite retourner un fichier, il faut ouvrir un « fichier » dans la mémoire php.
Pour cela, on utilise la fonction fopen avec comme argument php://output
$fp = fopen("php://output", 'w');
Cela permet de dire à PHP que l’on souhaite écrire dans la mémoire qui sera ensuite envoyée au navigateur.
Ensuite, pour des problèmes de compatibilités, les données que l’on exporte doivent être encodés en UTF-8
Pour cela, il faut ajouter l’UTF-8 BOM dans le fichier. Plus d’informations sont disponibles ici
fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ));
Ajout des en-têtes du tableau
Ensuite, On souhaite ajouter les clés de notre tableau comme en-tête de tableau de notre fichier php.
À l’aide de la fonction array_keys, on va pouvoir récupérer les clés du tableau.
Par la suite, la fonction fputcsv est utilisée afin d’ajouter une ligne au fichier CSV.
fputcsv($fp,array_keys($data[0]),$delimiter,$enclosure);
Ajout des données du tableau PHP
Pour ajouter toutes les données du tableau PHP dans le fichier CSV, on va procéder à une boucle foreach qui permet d’ajouter les éléments ligne par ligne :
foreach ($data as $fields) { fputcsv($fp, $fields,$delimiter,$enclosure); }
Enfin, il ne nous reste plus qu’à fermer le fichier puis arrêter le script
fclose($fp); die();
Note : Puisque l’on modifie les en-têtes http, il est important que ce script soit exécuté avant tout code HTML. Plus d’informations sur le sujet sont disponible dans la documentation PHP.
Fonction PHP complète
La fonction finale que l’on vient de créer est la suivante :
/** * * Exports an associative array into a CSV file using PHP. * * @see https://stackoverflow.com/questions/21988581/write-utf-8-characters-to-file-with-fputcsv-in-php * * @param array $data The table you want to export in CSV * @param string $filename The name of the file you want to export * @param string $delimiter The CSV delimiter you wish to use. The default ";" is used for a compatibility with microsoft excel * @param string $enclosure The type of enclosure used in the CSV file, by default it will be a quote " */ function export_data_to_csv($data,$filename='export',$delimiter = ';',$enclosure = '"') { // Tells to the browser that a file is returned, with its name : $filename.csv header("Content-disposition: attachment; filename=$filename.csv"); // Tells to the browser that the content is a csv file header("Content-Type: text/csv"); // I open PHP memory as a file $fp = fopen("php://output", 'w'); // Insert the UTF-8 BOM in the file fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) )); // I add the array keys as CSV headers fputcsv($fp,array_keys($data[0]),$delimiter,$enclosure); // Add all the data in the file foreach ($data as $fields) { fputcsv($fp, $fields,$delimiter,$enclosure); } // Close the file fclose($fp); // Stop the script die(); }
Le code est disponible sur github dans le repository xusifob/lib
N’hésitez pas à commenter sous cet article pour plus d’astuces ou de questions sur ce type de fonctions !
salut, je n’arrive pas à upload le fichier. aucun de mes browsers ne me propose de récupérer le fichier. je passe par un event (click) sur un bouton qui renvoi le traitement ci-dessus par un appel en ajax. je récupère bien les données de ma bdd: ajax renvoi bien le contenu sous une forme csv comme attendu. mais je n’ai pas accès à l’upload. pas de popup….. Je ne vois pas de html avant dans mon code…. Dans les En-têtes de la réponse : Connection: Keep-Alive Content-disposition attachment; filename=export.csv Content-Length 332 Content-Type text/csv;charset=UTF-8 Date Mon, 23 Sep 2019 14:34:12 GMT… Lire la suite »
Bonjour,
En effet, le téléchargement via Ajax n’est pas possible, si tu souhaites pouvoir le faire télécharger à l’utilisateur via un clic par exemple, il faut se rendre sur la page qui génère le fichier CSV via un lien direct vers cette page par exemple
Ok, merci pour l’astuce.
J’ai trouvé une toute autre solution dans mon cas.
En effet, je n’ai même pas pensé à le faire comme tu le dit car j’ai trop pris l’habitude de travailler via les events en ajax maintenant.
Bonjour, d’abord merci pour le tuto très intéressant et complet, j’en suis fan après avoir essuyer pas mal d’échec. J’aimerais savoir Ghibu qu’elle a été ta solution pour le téléchargement stp?
Bonjour, merci pour ce tutoriel, j’ai un soucis à la fin: rien ne se passe si je lance la fonction avec un bouton onclick ou si je fait un href vers php://output. Possible d’avoir de l’aide pour le téléchargement svp?
Tu peux essayer de voir le code ci-dessous, qui devrait fonctionner :
https://phpfiddle.tk/96a23230
Bonjour, tout d’abord merci pour ce tutorial.
J’ai un soucis dans la génération de mon excel, car à la suite des ligne csv il affiche mes données en format php (array, variable)
Quelqu’un pourrais m’aider ?
Bonjour Clément,
N’as tu pas laissé un var_dump() quelque part dans ton code ?
Ou alors le problème peut venir si ton tableau n’est pas sous le bon format, alors il peut générer des erreurs PHP