Exporter en CSV via PHP

Réponses:

308

J'utilise personnellement cette fonction pour créer du contenu CSV à partir de n'importe quel tableau.

function array2csv(array &$array)
{
   if (count($array) == 0) {
     return null;
   }
   ob_start();
   $df = fopen("php://output", 'w');
   fputcsv($df, array_keys(reset($array)));
   foreach ($array as $row) {
      fputcsv($df, $row);
   }
   fclose($df);
   return ob_get_clean();
}

Ensuite, vous pouvez demander à votre utilisateur de télécharger ce fichier en utilisant quelque chose comme:

function download_send_headers($filename) {
    // 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");

    // disposition / encoding on response body
    header("Content-Disposition: attachment;filename={$filename}");
    header("Content-Transfer-Encoding: binary");
}

Exemple d'utilisation:

download_send_headers("data_export_" . date("Y-m-d") . ".csv");
echo array2csv($array);
die();
Alain Tiemblo
la source
1
sur le serveur local, cela fonctionne, mais dans un serveur distant, il affiche une nouvelle page avec du contenu et aucune fenêtre de téléchargement (désolé pour mon anglais)
khaled_webdev
2
Il peut y avoir plusieurs raisons aux erreurs, le moyen le plus simple de les trouver est de consulter votre fichier apache error.log.
Alain Tiemblo
7
Vous devez mettre un die();appel juste après echo array2csv();, éditera ma réponse. Assurez-vous de générer votre csv avant de sortir quelque chose dans votre page.
Alain Tiemblo
1
@ ring0 Je suppose que mettre la date passée dans l'en-tête désactive la mise en cache de la page, regardez le 2ème exemple php.net/manual/en/function.header.php
Abhishek Madhani
2
Donne des types mime à votre navigateur afin que vous obteniez un téléchargement modal au lieu du csv rendu dans la fenêtre actuelle.
Alain Tiemblo
32

Vous pouvez exporter la date à l'aide de cette commande.

<?php

$list = array (
    array('aaa', 'bbb', 'ccc', 'dddd'),
    array('123', '456', '789'),
    array('"aaa"', '"bbb"')
);

$fp = fopen('file.csv', 'w');

foreach ($list as $fields) {
    fputcsv($fp, $fields);
}

fclose($fp);
?>

Vous devez d'abord charger les données du serveur mysql dans un tableau

ynh
la source
10
Ou, vous pouvez faire le fputcsv () dans une boucle assoc fetch standard et le replacer directement à partir des résultats retournés.
DampeS8N
10
@ DampeS8N, +1 pour l'utilisation de "plop it down straight out" dans une phrase.
AnchovyLegend
ceci est copié sans attribution du manuel PHP pour fputcsv
BenK
14

Pour mémoire, la concaténation est waaaaaay plus rapide (je le pense) que fputcsvou même implode; Et la taille du fichier est plus petite:

// The data from Eternal Oblivion is an object, always
$values = (array) fetchDataFromEternalOblivion($userId, $limit = 1000);

// ----- fputcsv (slow)
// The code of @Alain Tiemblo is the best implementation
ob_start();
$csv = fopen("php://output", 'w');
fputcsv($csv, array_keys(reset($values)));
foreach ($values as $row) {
    fputcsv($csv, $row);
}
fclose($csv);
return ob_get_clean();

// ----- implode (slow, but file size is smaller)
$csv = implode(",", array_keys(reset($values))) . PHP_EOL;
foreach ($values as $row) {
    $csv .= '"' . implode('","', $row) . '"' . PHP_EOL;
}
return $csv;
// ----- concatenation (fast, file size is smaller)
// We can use one implode for the headers =D
$csv = implode(",", array_keys(reset($values))) . PHP_EOL;
$i = 1;
// This is less flexible, but we have more control over the formatting
foreach ($values as $row) {
    $csv .= '"' . $row['id'] . '",';
    $csv .= '"' . $row['name'] . '",';
    $csv .= '"' . date('d-m-Y', strtotime($row['date'])) . '",';
    $csv .= '"' . ($row['pet_name'] ?: '-' ) . '",';
    $csv .= PHP_EOL;
}
return $csv;

C'est la conclusion de l'optimisation de plusieurs rapports, de dix à des milliers de lignes. Les trois exemples fonctionnaient bien sous 1000 lignes, mais échouaient lorsque les données étaient plus volumineuses.

Axel A. García
la source
9

Je recommande parsecsv-for-php pour contourner un certain nombre de problèmes avec les nouvelles lignes et les citations imbriquées.

StigM
la source
8

Fonctionne avec plus de 100 lignes, si vous spécifiez la taille du fichier dans les en-têtes, appelez simplement la méthode get () dans votre propre classe

function setHeader($filename, $filesize)
{
    // disable caching
    $now = gmdate("D, d M Y H:i:s");
    header("Expires: Tue, 01 Jan 2001 00:00:01 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");
    header('Content-Type: text/x-csv');

    // disposition / encoding on response body
    if (isset($filename) && strlen($filename) > 0)
        header("Content-Disposition: attachment;filename={$filename}");
    if (isset($filesize))
        header("Content-Length: ".$filesize);
    header("Content-Transfer-Encoding: binary");
    header("Connection: close");
}

function getSql()
{
    // return you own sql
    $sql = "SELECT id, date, params, value FROM sometable ORDER BY date;";
    return $sql;
}

function getExportData()
{
    $values = array();

    $sql = $this->getSql();
    if (strlen($sql) > 0)
    {
        $result = dbquery($sql); // opens the database and executes the sql ... make your own ;-) 
        $fromDb = mysql_fetch_assoc($result);
        if ($fromDb !== false)
        {
            while ($fromDb)
            {
                $values[] = $fromDb;
                $fromDb = mysql_fetch_assoc($result);
            }
        }
    }
    return $values;
}

function get()
{
    $values = $this->getExportData(); // values as array 
    $csv = tmpfile();

    $bFirstRowHeader = true;
    foreach ($values as $row) 
    {
        if ($bFirstRowHeader)
        {
            fputcsv($csv, array_keys($row));
            $bFirstRowHeader = false;
        }

        fputcsv($csv, array_values($row));
    }

    rewind($csv);

    $filename = "export_".date("Y-m-d").".csv";

    $fstat = fstat($csv);
    $this->setHeader($filename, $fstat['size']);

    fpassthru($csv);
    fclose($csv);
}
Bernhard Leichtle
la source
6

Tout comme @ Dampes8N a dit:

$result = mysql_query($sql,$conecction);
$fp = fopen('file.csv', 'w');
while($row = mysql_fetch_assoc($result)){
    fputcsv($fp, $row);
}
fclose($fp);

J'espère que cela t'aides.

les racines
la source