web-dev-qa-db-fra.com

Forcer fputcsv à utiliser le boîtier pour * tous * les champs

Lorsque j'utilise fputcsv pour écrire une ligne dans un descripteur de fichier ouvert, PHP ajoutera un caractère englobant à toute colonne qui, selon lui, en a besoin, mais laissera les autres colonnes sans les enceintes.

Par exemple, vous pourriez vous retrouver avec une ligne comme celle-ci

11,"Bob ",Jenkins,"200 main st. USA ",etc

À moins d'ajouter un espace faux à la fin de chaque champ, existe-t-il un moyen de forcer fputcsv à toujours entourer les colonnes avec le caractère Enclosure (par défaut un ")?

38
Alan Storm

Non, fputcsv () enferme le champ uniquement dans les conditions suivantes

/* enclose a field that contains a delimiter, an Enclosure character, or a newline */
if (FPUTCSV_FLD_CHK(delimiter) ||
  FPUTCSV_FLD_CHK(Enclosure) ||
  FPUTCSV_FLD_CHK(escape_char) ||
  FPUTCSV_FLD_CHK('\n') ||
  FPUTCSV_FLD_CHK('\r') ||
  FPUTCSV_FLD_CHK('\t') ||
  FPUTCSV_FLD_CHK(' ')
)

Il n'y a pas d'option "toujours entourer".

28
VolkerK

Pas content de cette solution mais c'est ce que j'ai fait et travaillé. L'idée est de définir un caractère vide comme caractère de boîtier sur fputcsv et d'ajouter des guillemets sur chaque élément de votre tableau.

function encodeFunc($value) {
    return "\"$value\"";
}

fputcsv($handler, array_map(encodeFunc, $array), ',', chr(0));
19

En s'appuyant sur la réponse de Martin , si vous voulez éviter d'insérer des caractères qui ne proviennent pas du tableau source (Chr(127), Chr(0), etc.) , vous pouvez remplacer la ligne fputcsv () par ce qui suit à la place:

fputs($fp, implode(",", array_map("encodeFunc", $row))."\r\n");

Certes, fputs () est plus lent que fputcsv (), mais c'est une sortie plus propre. Le code complet est donc:

/***
 * @param $value array
 * @return string array values enclosed in quotes every time.
 */
function encodeFunc($value) {
    ///remove any ESCAPED double quotes within string.
    $value = str_replace('\\"','"',$value);
    //then force escape these same double quotes And Any UNESCAPED Ones.
    $value = str_replace('"','\"',$value);
    //force wrap value in quotes and return
    return '"'.$value.'"';
}

$fp = fopen("filename.csv", 'w');
foreach($table as $row){
    fputs($fp, implode(",", array_map("encodeFunc", $row))."\r\n");
}
fclose($fp);
17
dearsina

Après beaucoup de mises au rebut et de vérifications de caractères quelque peu fastidieuses, j'ai une version des codes référencés ci-dessus par Diego et Mahn qui supprimera correctement les enveloppes et les remplacera par des doubles des guillemets sur tous les champs dans fputcsv. puis exportez le fichier vers le navigateur pour le télécharger.

J'ai également eu un problème secondaire de ne pas pouvoir être sûr que les guillemets doubles étaient toujours/jamais échappés.

Spécifiquement pour la sortie directement vers le navigateur en utilisant le flux d'entrée php: // tel que référencé par Diego. Chr(127) est un caractère espace, le fichier CSV a donc quelques espaces de plus qu'autrement, mais je pense que cela évite le problème de chr(0) caractères NULS en UTF-8.

/***
 * @param $value array
 * @return string array values enclosed in quotes every time.
 */
function encodeFunc($value) {
    ///remove any ESCAPED double quotes within string.
    $value = str_replace('\\"','"',$value);
    //then force escape these same double quotes And Any UNESCAPED Ones.
    $value = str_replace('"','\"',$value);
    //force wrap value in quotes and return
    return '"'.$value.'"';
}


$result = $array_Set_Of_DataBase_Results;
$fp = fopen('php://output', 'w');
if ($fp && $result) {
    header('Content-Type: text/csv');
    header('Content-Disposition: attachment; filename="export-'.date("d-m-Y").'.csv"');
    foreach($result as $row) {
        fputcsv($fp, array_map("encodeFunc", $row), ',', chr(127));
    }
    unset($result,$row);
    die;
}

J'espère que cela est utile pour quelqu'un.

3
Martin