Code PHP pour convertir une requête MySQL en CSV [fermé]

128

Quel est le moyen le plus efficace de convertir une requête MySQL en CSV en PHP s'il vous plaît?

Il serait préférable d'éviter les fichiers temporaires car cela réduit la portabilité (chemins de répertoire et configuration des autorisations du système de fichiers requises).

Le CSV doit également inclure une ligne supérieure de noms de champ.

Reilly Beacom
la source
74
Pourquoi cette question a-t-elle été fermée comme non constructive? Celui-ci est beau et parfaitement clair.
14
@Alec Parce que certains modérateurs ici sont des super modérateurs, vous savez ... "Avec les superpuissances, il y a une grande responsabilité!" - Uncle Ben
finitenessofinfinity
18
Le pouvoir @finitenessofinfinity corrompt, le pouvoir absolu corrompt absolument. Stackoverflow en est un excellent exemple.
16
Je vote pour rouvrir cette question!
TN888
9
Six mois plus tard et j'utilise les réponses à cela dans mon site Web. Cela peut-il être rouvert?
Jon

Réponses:

138
SELECT * INTO OUTFILE "c:/mydata.csv"
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY "\n"
FROM my_table;

( la documentation à ce sujet est ici: http://dev.mysql.com/doc/refman/5.0/en/select.html )

ou:

$select = "SELECT * FROM table_name";

$export = mysql_query ( $select ) or die ( "Sql error : " . mysql_error( ) );

$fields = mysql_num_fields ( $export );

for ( $i = 0; $i < $fields; $i++ )
{
    $header .= mysql_field_name( $export , $i ) . "\t";
}

while( $row = mysql_fetch_row( $export ) )
{
    $line = '';
    foreach( $row as $value )
    {                                            
        if ( ( !isset( $value ) ) || ( $value == "" ) )
        {
            $value = "\t";
        }
        else
        {
            $value = str_replace( '"' , '""' , $value );
            $value = '"' . $value . '"' . "\t";
        }
        $line .= $value;
    }
    $data .= trim( $line ) . "\n";
}
$data = str_replace( "\r" , "" , $data );

if ( $data == "" )
{
    $data = "\n(0) Records Found!\n";                        
}

header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=your_desired_name.xls");
header("Pragma: no-cache");
header("Expires: 0");
print "$header\n$data";
Geoff
la source
5
techniquement, c'est séparé par des tabulations;)
John Douthat
5
Notez l'utilisation de barres obliques avec SELECT INTO OUTFILEmême sur Windows.
Johan
1
Hii cela fonctionne bien pour le format xls mais si j'essaie d'enregistrer en tant que fichier CSV, tous les résultats s'affichent dans 1 colonne. Je veux l'enregistrer en tant que fichier csv.
vinod reddy
Parmi au-dessus de deux, lequel est le meilleur, le plus sûr et pourquoi?
Chella
1
J'aurais tendance à suggérer que la deuxième option est plus sûre car `SELECT INTO OUTFILE nécessite que l'utilisateur mysql ait accès au système de fichiers pour modifier les fichiers, ce qui représente un risque potentiellement important.
Jeepstone
91

Découvrez cette question / réponse . Il est plus concis que celui de @ Geoff et utilise également la fonction intégrée fputcsv.

$result = $db_con->query('SELECT * FROM `some_table`');
if (!$result) die('Couldn\'t fetch records');
$num_fields = mysql_num_fields($result);
$headers = array();
for ($i = 0; $i < $num_fields; $i++) {
    $headers[] = mysql_field_name($result , $i);
}
$fp = fopen('php://output', 'w');
if ($fp && $result) {
    header('Content-Type: text/csv');
    header('Content-Disposition: attachment; filename="export.csv"');
    header('Pragma: no-cache');
    header('Expires: 0');
    fputcsv($fp, $headers);
    while ($row = $result->fetch_array(MYSQLI_NUM)) {
        fputcsv($fp, array_values($row));
    }
    die;
}
Jrgns
la source
1
Le vôtre n'a pas les en-têtes de colonne.
Paolo Bergantino
15
Au cas où quelqu'un d'autre serait aussi stupide que moi, ne le remplacez pas php://outputpar un nom de fichier réel ou n'essayez pas de le fermer par un fcloseà la fin: ce n'est pas un vrai fichier, juste un alias pour le flux de sortie. Quoi qu'il en soit, cette réponse a parfaitement fonctionné pour moi, merci Jrgns!
J.Steve
@ J.Steve Mon plaisir :)
Jrgns
10
Utilisation de mysqli: gist.github.com/jaredrummler/2bfcf48b48d3fefd50c2
Jared Rummler
1
mysql_num_fields () ne fonctionne pas pour moi et les en-têtes ne sont pas générés. Cette fonction est-elle obsolète ou quelque chose?
Doug
20

Consultez la documentation concernant la syntaxe SELECT ... INTO OUTFILE.

SELECT a,b,a+b INTO OUTFILE '/tmp/result.txt'
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM test_table;
nickf
la source
18

Une mise à jour de la solution @jrgns (avec quelques légères différences de syntaxe).

$result = mysql_query('SELECT * FROM `some_table`'); 
if (!$result) die('Couldn\'t fetch records'); 
$num_fields = mysql_num_fields($result); 
$headers = array(); 
for ($i = 0; $i < $num_fields; $i++) 
{     
       $headers[] = mysql_field_name($result , $i); 
} 
$fp = fopen('php://output', 'w'); 
if ($fp && $result) 
{     
       header('Content-Type: text/csv');
       header('Content-Disposition: attachment; filename="export.csv"');
       header('Pragma: no-cache');    
       header('Expires: 0');
       fputcsv($fp, $headers); 
       while ($row = mysql_fetch_row($result)) 
       {
          fputcsv($fp, array_values($row)); 
       }
die; 
} 
John M
la source
Pour une raison quelconque, $ fp me renvoie false.
Volatil3
Pour MySQL moderne, vous pouvez utiliser: $ headers [] = mysqli_fetch_field_direct ($ result, $ i) -> nom;
Ben en Californie
Et changez les autres fonctions mysql_ en fonctions mysqli_.
Ben en Californie
6

Si vous souhaitez que le téléchargement soit proposé sous forme de téléchargement pouvant être ouvert directement dans Excel, cela peut fonctionner pour vous: (copié à partir d'un ancien projet inédit)

Ces fonctions configurent les en-têtes:

function setExcelContentType() {
    if(headers_sent())
        return false;

    header('Content-type: application/vnd.ms-excel');
    return true;
}

function setDownloadAsHeader($filename) {
    if(headers_sent())
        return false;

    header('Content-disposition: attachment; filename=' . $filename);
    return true;
}

Celui-ci envoie un CSV à un flux en utilisant un résultat mysql

function csvFromResult($stream, $result, $showColumnHeaders = true) {
    if($showColumnHeaders) {
        $columnHeaders = array();
        $nfields = mysql_num_fields($result);
        for($i = 0; $i < $nfields; $i++) {
            $field = mysql_fetch_field($result, $i);
            $columnHeaders[] = $field->name;
        }
        fputcsv($stream, $columnHeaders);
    }

    $nrows = 0;
    while($row = mysql_fetch_row($result)) {
        fputcsv($stream, $row);
        $nrows++;
    }

    return $nrows;
}

Celui-ci utilise la fonction ci-dessus pour écrire un CSV dans un fichier, donné par $ filename

function csvFileFromResult($filename, $result, $showColumnHeaders = true) {
    $fp = fopen($filename, 'w');
    $rc = csvFromResult($fp, $result, $showColumnHeaders);
    fclose($fp);
    return $rc;
}

Et c'est là que la magie opère;)

function csvToExcelDownloadFromResult($result, $showColumnHeaders = true, $asFilename = 'data.csv') {
    setExcelContentType();
    setDownloadAsHeader($asFilename);
    return csvFileFromResult('php://output', $result, $showColumnHeaders);
}

Par exemple:

$result = mysql_query("SELECT foo, bar, shazbot FROM baz WHERE boo = 'foo'");
csvToExcelDownloadFromResult($result);
John Douthat
la source
1
Merci john code très utile. J'ai dû modifier une ligne pour la fonction csvFromResult. au lieu de while ($ row = mysql_fetch_row ($ result)) {fputcsv ($ stream, $ row); $ lignes ++; }, j'ai dû utiliser while ($ row = mysql_fetch_row ($ result)) {$ data [] = $ row; // fputcsv ($ stream, $ row); // $ lignes ++; } foreach ($ data as $ d) {fputcsv ($ stream, $ d); }. merci encore pour un code si merveilleux.
codingbbq
3
// Export to CSV
if($_GET['action'] == 'export') {

  $rsSearchResults = mysql_query($sql, $db) or die(mysql_error());

  $out = '';
  $fields = mysql_list_fields('database','table',$db);
  $columns = mysql_num_fields($fields);

  // Put the name of all fields
  for ($i = 0; $i < $columns; $i++) {
    $l=mysql_field_name($fields, $i);
    $out .= '"'.$l.'",';
  }
  $out .="\n";

  // Add all values in the table
  while ($l = mysql_fetch_array($rsSearchResults)) {
    for ($i = 0; $i < $columns; $i++) {
      $out .='"'.$l["$i"].'",';
    }
    $out .="\n";
  }
  // Output to browser with appropriate mime type, you choose ;)
  header("Content-type: text/x-csv");
  //header("Content-type: text/csv");
  //header("Content-type: application/csv");
  header("Content-Disposition: attachment; filename=search_results.csv");
  echo $out;
  exit;
}
Wayne
la source