Comment convertir un tableau en fichier CSV?
Voici mon tableau:
stdClass Object
(
[OrderList_RetrieveByContactResult] => stdClass Object
(
[OrderDetails] => stdClass Object
(
[entityId] => 1025298
[orderId] => 10952
[orderName] => testing
[statusTypeId] => 4652
[countryCode] => AU
[orderType] => 1
[invoiceNumber] => 0
[invoiceDate] => 0001-01-01T00:00:00
[userID_AssignedTo] => 11711
[shippingAmount] => 8.95
[shippingTaxRate] => 0
[shippingAttention] =>
[shippingInstructions] =>
[shippingOptionId] => 50161
[discountCodeId] => 0
[discountRate] => 0
[totalOrderAmount] => 408.45
[directDebitTypeId] => 0
[directDebitDays] => 0
[isRecur] =>
[nextInvoiceDate] => 0001-01-01T00:00:00
[endRecurDate] => 0001-01-01T00:00:00
[cycleTypeID] => 1
[createDate] => 2010-10-08T18:40:00
[lastUpdateDate] => 2010-10-08T18:40:00
[deleted] =>
[products] => stdClass Object
(
[Product] => stdClass Object
(
[productId] => 674975
[productCode] =>
[productDescription] =>
[units] => 10
[unitPrice] => 39.95
[unitTaxRate] => 0
[totalProductPrice] => 399.5
[productName] => Acne Clearing Gel
)
)
[addresses] => stdClass Object
(
[Address] => stdClass Object
(
[addressTypeID] => 8
[addressLine1] => Cebu City
[city] => Cebu
[zipcode] => 6000
[state] =>
[countryCode] => PH
)
)
)
)
)
J'utilise la fonction suivante pour cela; c'est une adaptation de l'une des entrées man dans les commentaires fputscsv. Et vous voudrez probablement aplatir ce tableau; je ne sais pas ce qui se passe si vous passez dans un multi-dimensionnel.
/**
* Formats a line (passed as a fields array) as CSV and returns the CSV as a string.
* Adapted from http://us3.php.net/manual/en/function.fputcsv.php#87120
*/
function arrayToCsv( array &$fields, $delimiter = ';', $Enclosure = '"', $encloseAll = false, $nullToMysqlNull = false ) {
$delimiter_esc = preg_quote($delimiter, '/');
$Enclosure_esc = preg_quote($Enclosure, '/');
$output = array();
foreach ( $fields as $field ) {
if ($field === null && $nullToMysqlNull) {
$output[] = 'NULL';
continue;
}
// Enclose fields containing $delimiter, $Enclosure or whitespace
if ( $encloseAll || preg_match( "/(?:${delimiter_esc}|${Enclosure_esc}|\s)/", $field ) ) {
$output[] = $Enclosure . str_replace($Enclosure, $Enclosure . $Enclosure, $field) . $Enclosure;
}
else {
$output[] = $field;
}
}
return implode( $delimiter, $output );
}
Ma solution nécessite que le tableau soit formaté différemment de celui fourni dans la question:
<?
$data = array(
array( 'row_1_col_1', 'row_1_col_2', 'row_1_col_3' ),
array( 'row_2_col_1', 'row_2_col_2', 'row_2_col_3' ),
array( 'row_3_col_1', 'row_3_col_2', 'row_3_col_3' ),
);
?>
Nous définissons notre fonction:
<?
function outputCSV($data) {
$outputBuffer = fopen("php://output", 'w');
foreach($data as $val) {
fputcsv($outputBuffer, $val);
}
fclose($outputBuffer);
}
?>
Ensuite, nous sortons nos données au format CSV:
<?
$filename = "example";
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename={$filename}.csv");
header("Pragma: no-cache");
header("Expires: 0");
outputCSV($data);
?>
Je l'ai utilisé avec plusieurs projets et cela fonctionne bien. Je dois noter que le code outputCSV
est plus intelligent que moi, donc je suis sûr que je ne suis pas l'auteur original. Malheureusement, j'ai perdu la trace d'où je l'ai obtenu, donc je ne peux pas donner le crédit à qui il est dû.
Une légère adaptation à la solution ci-dessus par kingjeffrey pour quand vous voulez créer et faire écho au CSV dans un modèle (c'est-à-dire que la plupart des frameworks auront la mise en mémoire tampon de sortie activée et vous devez définir des en-têtes, etc. dans les contrôleurs.)
// Create Some data
<?php
$data = array(
array( 'row_1_col_1', 'row_1_col_2', 'row_1_col_3' ),
array( 'row_2_col_1', 'row_2_col_2', 'row_2_col_3' ),
array( 'row_3_col_1', 'row_3_col_2', 'row_3_col_3' ),
);
// Create a stream opening it with read / write mode
$stream = fopen('data://text/plain,' . "", 'w+');
// Iterate over the data, writting each line to the text stream
foreach ($data as $val) {
fputcsv($stream, $val);
}
// Rewind the stream
rewind($stream);
// You can now echo it's content
echo stream_get_contents($stream);
// Close the stream
fclose($stream);
Mention à Kingjeffrey ci-dessus et aussi à cela article de blog où j'ai trouvé les informations sur la création de flux de texte.
function array_2_csv($array) {
$csv = array();
foreach ($array as $item) {
if (is_array($item)) {
$csv[] = array_2_csv($item);
} else {
$csv[] = $item;
}
}
return implode(',', $csv);
}
$csv_data = array_2_csv($array);
echo "<pre>";
print_r($csv_data);
echo '</pre>' ;
La réponse acceptée de Paul est excellente. J'ai fait une petite extension à cela qui est très utile si vous avez un tableau multidimensionnel comme celui-ci (ce qui est assez courant):
Array
(
[0] => Array
(
[a] => "a"
[b] => "b"
)
[1] => Array
(
[a] => "a2"
[b] => "b2"
)
[2] => Array
(
[a] => "a3"
[b] => "b3"
)
[3] => Array
(
[a] => "a4"
[b] => "b4"
)
[4] => Array
(
[a] => "a5"
[b] => "b5"
)
)
J'ai donc pris la fonction de Paul d'en haut:
/**
* Formats a line (passed as a fields array) as CSV and returns the CSV as a string.
* Adapted from http://us3.php.net/manual/en/function.fputcsv.php#87120
*/
function arrayToCsv( array &$fields, $delimiter = ';', $Enclosure = '"', $encloseAll = false, $nullToMysqlNull = false ) {
$delimiter_esc = preg_quote($delimiter, '/');
$Enclosure_esc = preg_quote($Enclosure, '/');
$output = array();
foreach ( $fields as $field ) {
if ($field === null && $nullToMysqlNull) {
$output[] = 'NULL';
continue;
}
// Enclose fields containing $delimiter, $Enclosure or whitespace
if ( $encloseAll || preg_match( "/(?:${delimiter_esc}|${Enclosure_esc}|\s)/", $field ) ) {
$output[] = $Enclosure . str_replace($Enclosure, $Enclosure . $Enclosure, $field) . $Enclosure;
}
else {
$output[] = $field;
}
}
return implode( $delimiter, $output );
}
Et ajouté ceci:
function a2c($array, $glue = "\n")
{
$ret = [];
foreach ($array as $item) {
$ret[] = arrayToCsv($item);
}
return implode($glue, $ret);
}
Vous pouvez donc simplement appeler:
$csv = a2c($array);
Si vous voulez une fin de ligne spéciale, vous pouvez utiliser le paramètre facultatif "colle" pour cela.