PHP exporter des données au format csv stocké dans une base MySQL
Intro
J’ai été amené à réaliser export de données au format csv à partir d’une base MySQL pour le compte d’un client.
Mon premier réflexe a été de voir du côté de phpmyadmin, puis d’utiliser la fonction d’export intégrée.
Après avoir réalisé la requête sql, je me suis confronté à une limite, il n’est pas possible d’exporter plus de 500 lignes à la fois … (je n’ai pas trouvé la manip pour exporter plus ???)
Deuxième réalité, je serai amené à réaliser plusieurs fois des exports et donc refaire la manipulation à chaque fois …
Pourquoi ne pas mettre en place un script PHP qui va permettre :
- au client d’être autonome
- et moi de réaliser rapidement la tâche ?
J’ai donc décidé de créer un bouton, dans une page html du backoffice , d’export des données.
Derrière le bouton, il y a une class php qui va réaliser les tâches suivantes :
- créer un fichier temporaire csv sur la machine
- qui va contenir toutes colonnes définies dans un SELECT
- dans le même dossier que le script de lancement
index.php
- modifier l’entête http pour avoir la pop up d’upload du navigateur proposant le fichier csv
- supprimer le fichier temporaire
- utilisable avec deux technologies de connexion :
- mysql_ (un peu old school mais je vois encore régulièrement cette technologie en action)
- et PDO
- Attention : les champs de type VARBINARY et BLOG sont mal générés
La class UploadCSV
Voici la class PHP UploadCSV, dans le fichier class-exportcsv.php :
<?php
class UploadCSV
{
protected $PdoDBConnection ;
protected $outputfileName ;
protected $pathCSV ;
protected $sqlSelect ;
protected $quoteColon ;
protected $separator ;
public function __construct(array $init){
$default_init = array(
'PdoDBConnection' => NULL,
'outputfileName' => "export_" . date("Y-m-d-H-i-s") . ".csv",
'pathCSV' => "./export-".uniqid() ,
'sqlSelect' => NULL,
'quoteColon' => NULL,
'separator' => ",",
);
$init = array_merge($default_init, $init);
$this->setDBConnection($init['PdoDBConnection']);
$this->setoutputfileName($init['outputfileName']);
$this->setpathCSV($init['pathCSV']);
$this->setsqlSelect($init['sqlSelect']);
$this->setquoteColon($init['quoteColon']);
$this->setseparator($init['separator']);
}
private function mySqlSelect(){
$result = array();
$sql_all_client = $this->sqlSelect;
$r = mysql_query($sql_all_client);
while($row = mysql_fetch_object($r)){
$result[] = $row;
}
return $result;
}
public function PdoSelect(){
$result = array();
$bdd = $this->PdoDBConnection ;
$bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$bdd->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
$sql_all_client = $this->sqlSelect;
$stmt = $bdd->prepare($sql_all_client);
$stmt->execute();
$r = $stmt->fetchAll();
$stmt->closeCursor();
$stmt=NULL;
foreach ($r as $row) {
$result[] = $row;
}
return $result;
}
private function csv_headers($outputfileName,$pathCSV) {
// disable caching
$now = gmdate("D, d M Y H:i:s");
header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
header("Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate");
header("Last-Modified: {$now} GMT");
// force download
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
// file weight
header("Content-Length: " . filesize($pathCSV));
// encrypt output in utf-8
header('Content-Type: text/html; charset=utf-8');
// disposition / encoding on response body
header("Content-Disposition: attachment;filename={$outputfileName}");
header("Content-Transfer-Encoding: binary");
}
private function createcsv($pathCSV,$data){
$myfile = fopen($pathCSV, 'w');
/*générer la ligne de titre*/
$title = $data[0];
$txt = "";
$j=0;
foreach ($title as $key => $value) {
if($this->quoteColon == "*"){
$txt .= "'".$key.$this->separator;
}elseif (is_array ($this->quoteColon)){
if(in_array($j,$this->quoteColon)){
$txt .= "'".$key.$this->separator;
}else{
$txt .= $key.$this->separator;
}
}else{
$txt .= $key.$this->separator;
}
$j++;
}
$this->cleanBrWrite($myfile, $txt);
/*fin générer la ligne de titre*/
/*générer les lignes de corps*/
foreach ($data as $d) {
$txt = "";
$j=0;
foreach ($d as $i) {
if($this->quoteColon == "*"){
$txt .= "'".$i.$this->separator;
}elseif (is_array ($this->quoteColon)){
if(in_array($j,$this->quoteColon)){
$txt .= "'".$i.$this->separator;
}else{
$txt .= $i.$this->separator;
}
}else{
$txt .= $i.$this->separator;
}
$j++;
}
$this->cleanBrWrite($myfile, $txt);
}
/*fin générer les lignes de corps*/
fclose($myfile);
}
private function cleanBrWrite($file, $txt){
/*supprimer la dernière virgule de la ligne*/
$txt = rtrim($txt, ",");
/*remplacer les retours chariots pr un espace*/
$txt = str_replace(array("\r", "\n"), ' ', $txt);
/*remplacer les ; par un rien (Excel interprète ; comme des tabulation)*/
$txt = str_replace(array(";"), '', $txt);
/*Passer à la ligne*/
$txt = $txt."\n";
fwrite($file, $txt);
}
public function generate(){
/*récupérer les données */
if($this->PdoDBConnection){
$data = $this->PdoSelect();
}else{
$data = $this->mySqlSelect();
}
/*création du fichier csv dans le serveur */
$this->createcsv($this->pathCSV , $data);
/*changer le header HTTP */
$this->csv_headers($this->outputfileName , $this->pathCSV);
/*lire le fichier csv */
readfile($this->pathCSV);
/*supprimer le fichier csv du serveur */
unlink($this->pathCSV);
die();
}
private function setDBConnection($info){
if($info){
$this->PdoDBConnection = $info;
}
}
private function setoutputfileName($info){
if($info){
$this->outputfileName = $info;
}else{
die('outputfileName - la valeur ne peut pas etre null');
}
}
private function setpathCSV($info){
if($info){
$this->pathCSV = $info;
}else{
throw new Exception('pathCSV - la valeur ne peut pas etre null');
}
}
private function setsqlSelect($info){
if($info){
$this->sqlSelect = $info;
}else{
throw new Exception('sqlSelect - la valeur ne peut pas etre null');
}
}
private function setquoteColon($info){
if($info){
$this->quoteColon = $info;
}else{
$this->quoteColon = NULL;
}
}
private function setseparator($info){
if($info){
$this->separator = $info;
}else{
throw new Exception('separator - la valeur ne peut pas etre null');
}
}
}
Utiliser la class UploadCSV avec mysql_connect
Dans le fichier index.php :
<?php
require_once 'class-exportcsv.php';
$sql = 'SELECT * FROM `clients` ORDER BY `id_client` ASC';
$host = 'localhost';
$bdname = 'bdd_name';
$user = 'root';
$password = '';
$link = mysql_connect($host,$user, $password);
if (!$link) {
die('Could not connect: ' . mysql_error());
}
$BddSelect = mysql_select_db ( $bdname , $link );
if (!$BddSelect) {
die('Could not connect: ' . mysql_error());
}
$init = array(
'PdoDBConnection' => NULL, // obligatoire
'sqlSelect' => $sql, // obligatoire à définir
'outputfileName' => "client_" . date("Y-m-d-H-i-s") . ".csv", // par défaut "export_" . date("Y-m-d-H-i-s") . ".csv"
'pathCSV' => "./txt-".uniqid() , // par défaut "./export-".uniqid()
'quoteColon' => array(4,11), // par défaut NULL - * tous les champs avec quote - certaine colonne array(1,2) à partir de 0
'separator' => "|", // par défaut ,
);
$csv = new UploadCSV($init);
$csv->generate();
Utiliser la class UploadCSV avec PDO
Dans le fichier index.php :
<?php
require_once 'class-exportcsv.php';
$sql = 'SELECT * FROM `clients` ORDER BY `id_client` ASC';
$host = 'localhost';
$bdname = 'bdd_name';
$user = 'root';
$password = '';
$init = array(
'PdoDBConnection' => new PDO('mysql:host='.$host.';dbname='.$bdname, $user, $password), // obligatoire
'sqlSelect' => $sql, // obligatoire à définir
'outputfileName' => "client_" . date("Y-m-d-H-i-s") . ".csv", // par défaut "export_" . date("Y-m-d-H-i-s") . ".csv"
'pathCSV' => "./txt-".uniqid() , // par défaut "./export-".uniqid()
'quoteColon' => array(4,11), // par défaut NULL - * tous les champs avec quote - certaine colonne array(1,2) à partir de 0
'separator' => "|", // par défaut ,
);
$csv = new UploadCSV($init);
$csv->generate();