Dariusz.Staropietka.com » DEV

Jak przez PHP pobrać dane z mySQL do CSV?

Plik CSV (wartości rozdzielone przecinkami) to specjalny, bazodanowy, tekstowy typ pliku, który można tworzyć i edytować w różnych aplikacjach. Za sprawą uniformizacji formatu, dane (tekst i liczby) zapisane w pliku CSV można łatwo przenosić między programami i platformami. Można na przykład wyeksportować kontakty z usługi Google do pliku CSV, a następnie zaimportować je do programu Outlook. Czy to nie przyjemna wizja?

Po format CSV sięgnąłem za sprawą zlecenia, nad którym pracuję. Zleceniodawca poprosił, aby dane zbierane w bazie, mogły być eksportowane do formatu Excel'a - co z kolei miałoby znacząco usprawnić zarządzanie biznesem. Przyznam, że niespecjalnie chciało mi się badać, jak skonstruowane są pliki arkusza kalkulacyjnego Microsoftu, ale że wiedziałem, że aplikacja bez problemu obsługuje 'ceesfały', sięgnąłem właśnie po ten format.

Witryna, jaką buduję, posiada już system łączenia z bazą mySQL. Połączenie z nią i wykonanie zapytania jest więc bardzo proste:

require_once('ps/inc/config.php');
$query = mysqli_query($link, "select * FROM uczestnicy ORDER BY id ASC");

Testowa baza zawiera tabelę z dziewięcioma kolumnami i jakimiś śmieciami umieszczonymi w rekordach, zebranymi przez formularz rejestracji, umieszczony na stronie. Nazwy kolumn umieszczone w bazie, tożsame z polami formularza na stronie - są następujące: uczestnik,  praca,  email,  telefon,  firma,  siedziba,  poczta,  nip

Już na początku uznałem, że podczas przetwarzania danych w arkuszu kalkulacyjnym, takie opisy poszczególnych kolumn mogą nie być wystarczająco precyzyjne, przypisałem więc im inne, bardziej opisowe nazwy:

$uczestnik = 'Imię i nazwisko'; 
 $praca = 'Miejsce pracy';  
 $email = 'Adres e-mail'; 
 $telefon = 'Nr telefonu';
 $firma = 'Faktura: firma/imię i nazwisko';
 $siedziba = 'Faktura: ulica, nr domu/lokalu'; 
 $poczta = 'Faktura: kod pocztowy i poczta';
 $nip = 'NIP';

Wcześniej określiłem również nazewnictwo plików z wygenerowanymi raportami:

if($query->num_rows > 0){
    $delimiter = ",";
    $filename = "raport_" . date('Y-m-d') . ".csv";
    
    $f = fopen('php://memory', 'w');

Zebrane dane przetworzyłem rekord po rekordzie, sformatowałem zgodnie z CSV i wysłałem do 'wskaźnika pliku'. Na koniec dodałem nagłówki, dzięki którym raport nie zostanie wyświetlony, tylko pobrany i skierowałem do pobrania właśnie.

<?php

require_once('ps/inc/config.php');

$query = mysqli_query($link, "select * FROM uczestnicy ORDER BY id ASC");
 
if($query->num_rows > 0)
{
  $delimiter = ",";
  $filename = "raport_" . date('Y-m-d') . ".csv";

  $f = fopen('php://memory', 'w');
    
  $uczestnik = 'Imię i nazwisko'; 
  $praca = 'Miejsce pracy';  
  $email = 'Adres e-mail'; 
  $telefon = 'Nr telefonu';
  $firma = 'Faktura: firma/imię i nazwisko';
  $siedziba = 'Faktura: ulica, nr domu/lokalu'; 
  $poczta = 'Faktura: kod pocztowy i poczta';
  $nip = 'NIP';

  $fields = array('id', 'Imię i nazwisko', 'Miejsce pracy', 'Adres e-mail', 'Nr telefonu', 'Faktura: firma/imię i nazwisko', 'Faktura: ulica, nr domu/lokalu', 'Faktura: kod pocztowy i poczta', 'NIP');

  fputcsv($f, $fields, $delimiter);

  while($row = $query->fetch_assoc())
   {

   $lineData = array($row['id'], $row['uczestnik'], $row['praca'], $row['email'], $row['telefon'], $row['firma'], $row['siedziba'], $row['poczta'], $row['nip']);
   fputcsv($f, $lineData, $delimiter);
    }
    
  fseek($f, 0);

  header('Content-Type: text/csv');
  header('Content-Disposition: attachment; filename="' . $filename . '";');

  fpassthru($f);
}
exit;

?>

Efekt osiągnięty i dość przyjemny: