Ekspor ke CSV melalui PHP


Jawaban:


308

Saya pribadi menggunakan fungsi ini untuk membuat konten CSV dari array apa pun.

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();
}

Kemudian Anda dapat membuat pengguna mengunduh file itu menggunakan sesuatu seperti:

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");
}

Contoh penggunaan:

download_send_headers("data_export_" . date("Y-m-d") . ".csv");
echo array2csv($array);
die();

1
di server lokal berfungsi, tetapi di kejauhan ia menampilkan halaman baru dengan konten dan tanpa jendela unduhan (maaf untuk bahasa Inggris saya)
khaled_webdev

2
Mungkin ada beberapa alasan untuk kesalahan, cara paling sederhana untuk menemukannya adalah dengan melihat file apache error.log Anda.
Alain Tiemblo

7
Anda perlu die();menelepon setelah itu echo array2csv();, akan mengedit jawaban saya. Pastikan untuk membuat csv Anda sebelum mengeluarkan sesuatu di halaman Anda.
Alain Tiemblo

1
@ ring0 Saya kira meletakkan tanggal yang lalu di header menonaktifkan caching halaman, lihat contoh 2 php.net/manual/en/function.header.php
Abhishek Madhani

2
Memberikan tipe mime ke browser Anda sehingga Anda akan mendapatkan modal unduhan alih-alih csv yang diberikan di jendela saat ini.
Alain Tiemblo

32

Anda dapat mengekspor tanggal menggunakan perintah ini.

<?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);
?>

Pertama, Anda harus memuat data dari server mysql ke array


10
Atau, Anda dapat melakukan fputcsv () di dalam loop assoc assoc standar dan menjatuhkannya langsung dari hasil yang dikembalikan.
DampeS8N

10
@ DampeS8N, +1 untuk penggunaan "plop it down straight out" dalam kalimat.
AnchovyLegend

ini disalin tanpa atribusi dari manual PHP untuk fputcsv
BenK

14

Sekadar catatan, penggabungan adalah waaaaaay lebih cepat (maksud saya) daripada fputcsvatau bahkan implode; Dan ukuran file lebih kecil:

// 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;

Ini adalah kesimpulan dari optimalisasi beberapa laporan, dari sepuluh hingga ribuan baris. Tiga contoh bekerja dengan baik di bawah 1000 baris, tetapi gagal ketika data lebih besar.



8

Bekerja dengan lebih dari 100 baris, jika Anda menentukan ukuran file di header, panggil metode get () di kelas Anda sendiri

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);
}


6

Sama seperti @ Dampes8N berkata:

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

Semoga ini membantu.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.