Convert php array to csv string
Asked Answered
P

10

24

I have several method to transform php array to csv string both from stackoverflow and google. But I am in trouble that if I want to store mobile number such as 01727499452, it saves as without first 0 value. I am currently using this piece of code: Convert array into csv

Can anyone please help me.

Array   

[1] => Array
    (
        [0] => Lalu ' " ; \\ Kumar
        [1] => Mondal
        [2] => 01934298345
        [3] => 
    )

[2] => Array
    (
        [0] => Pritom
        [1] => Kumar Mondal
        [2] => 01727499452
        [3] => Bit Mascot
    )

[3] => Array
    (
        [0] => Pritom
        [1] => Kumar Mondal
        [2] => 01711511149
        [3] => 
    )

[4] => Array
    (
        [0] => Raaz
        [1] => Mukherzee
        [2] => 01911224589
        [3] => Khulna University 06
    )

)

My code block:

function arrayToCsv( array $fields, $delimiter = ';', $enclosure = '"', $encloseAll = false, $nullToMysqlNull = false ) {
$delimiter_esc = preg_quote($delimiter, '/');
$enclosure_esc = preg_quote($enclosure, '/');

$outputString = "";
foreach($fields as $tempFields) {
    $output = array();
    foreach ( $tempFields 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 ) ) {
            $field = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure;
        }
        $output[] = $field." ";
    }
    $outputString .= implode( $delimiter, $output )."\r\n";
}
return $outputString; }

Thanks,

Pritom.

Percolate answered 3/5, 2013 at 6:0 Comment(7)
That's the problem with using other people's wheels.Psychoactive
Save it as a string. I'd recommend that for phone numbers anyway, because you're just going to want to save that + as well ;)An
Can you give an example of how your array looks like?Cyclopedia
You should be using PHP's built in CSV functions like php.net/manual/en/function.fputcsv.phpAchene
Some second-hand advice: If you're not going to do arithmetic on it, store it as a string. The Daily WTF contains examples of many a phone number printed in scientific notation, which ultimately stems from someone storing it as an integer.Effeminize
@Steve, all here we are other people, so why we are here? If anyone can not find his answer himself, then need to use other people's wheels.Percolate
The number will be stored correctly in the CSV, with a leading zero; but when opened in MS Excel, then Excel will reformat it - either use a file format that supports format information already (not CSV) so that Excel doesn't apply its standard behaviour, or force it to be a formula string when saving ="01911224589"Sales
C
41

You could use str_putcsv function:

if(!function_exists('str_putcsv'))
{
    function str_putcsv($input, $delimiter = ',', $enclosure = '"')
    {
        // Open a memory "file" for read/write...
        $fp = fopen('php://temp', 'r+');
        // ... write the $input array to the "file" using fputcsv()...
        fputcsv($fp, $input, $delimiter, $enclosure);
        // ... rewind the "file" so we can read what we just wrote...
        rewind($fp);
        // ... read the entire line into a variable...
        $data = fread($fp, 1048576);
        // ... close the "file"...
        fclose($fp);
        // ... and return the $data to the caller, with the trailing newline from fgets() removed.
        return rtrim($data, "\n");
    }
 }

 $csvString = '';
 foreach ($list as $fields) {
     $csvString .= str_putcsv($fields);
 }

More about this on GitHub, a function created by @johanmeiring.

Craiova answered 3/5, 2013 at 7:5 Comment(4)
It's a minor thing but i think you meant $csvString .= str_putcsv($fp, $fields);. Missing the $ ;)Timaru
shouldn't it be str_putcsv($fields); instead of str_putcsv($fp, $fields);Ludvig
I liked this solution. I made one small modification when I "borrowed" it: ... $len = ftell($fp)+1; rewind($fp); $data = fread($fp,$len); ... and it seems to work. I didn't know what 1048576 represents, so I didn't want to use it directly.Jankey
Why not the original function by someone called Dave who posted it years earlier with $data = fgets($fp); (thus avoiding hardcoding 1048576)? But does anyone know why he got -1 points even though it seems to work well?Cambrai
L
26

This is what you need

$out = "";
foreach($array as $arr) {
    $out .= implode(",", $arr) . PHP_EOL;

}

It runs through your array creating a new line on each loop seperating the array values with a ",".

Lizzielizzy answered 3/5, 2013 at 6:22 Comment(5)
Is this what I want? Please read my question and if you are not clear please ask me.Percolate
It should be, i dont see why you wouldnt:) Give it a shot, and see if it meets your expectations.Lizzielizzy
I have used something similar in a number of situations, and it works well with a warning (or two). This breaks if some value in $arr has a ',' character in it. The csv format has ways to handle it that aren't being addressed addressed by this solution. Also, you are coding a Windows specific newline with "\r\n", which may cause problems in some situations. Using the constant PHP_EOL will result in more portable code.Obi
OP should maybe try to examine the contents of $outAusten
Does not even attempt to escape output properly. Expect corrupted data from this.Sexism
T
7

Inspired by @alexcristea's answer:

function array2csv($data, $delimiter = ',', $enclosure = '"', $escape_char = "\\")
{
    $f = fopen('php://memory', 'r+');
    foreach ($data as $item) {
        fputcsv($f, $item, $delimiter, $enclosure, $escape_char);
    }
    rewind($f);
    return stream_get_contents($f);
}

$list = array (
    array('aaa', 'bbb', 'ccc', 'dddd'),
    array('123', '456', '789'),
    array('"aaa"', '"bbb"')
);
var_dump(array2csv($list));
Toastmaster answered 24/6, 2020 at 10:7 Comment(0)
V
3

Are you sure the numbers are actually being saved without the leading zero? Have you looked at the actual CSV output in a text editor?

If you've just opened up the CSV file in a spreadsheet application, it is most likely the spreadsheet that is interpreting your telephone numbers as numeric values and dropping the zeros when displaying them. You can usually fix that in the spreadsheet by changing the formatting options on that particular column.

Vivyan answered 3/5, 2013 at 6:44 Comment(0)
E
1

This works for me and it piggy backs off PHP's built-in CSV functions. The nifty part about that is that it automatically correctly adds inverted commas around the relevant fields.

// Create an array of elements
$list = array(
    ['Name', 'age', 'Gender'],
    ['Bob', 20, 'Male'],
    ['John', 25, 'Male'],
    ['Jessica', 30, 'Female']
);

// Create an output buffer
$outputBuffer = fopen('php://temp', 'w');

// Loop through the array and write to the output buffer
foreach ($list as $fields) {
    fputcsv($outputBuffer, $fields);
}

// Rewind the output buffer
rewind($outputBuffer);

// Read the contents of the output buffer
$csvString = stream_get_contents($outputBuffer);

// Close the output buffer
fclose($outputBuffer);

// Output the CSV string
echo $csvString;
Endowment answered 29/6, 2023 at 7:47 Comment(0)
W
0

Since it's a CSV and not something like JSON, everything is going to be read as a string anyway so just convert your number to a string with:

  • (string)$variable
  • strval($variable) (which I would prefer here)
  • concatenate with an empty string like $variable . ''

PHP's gettype() would also be an option. You can type cast every field to a string (even if it already is one) by using one of the methods I described or you can call out just the number field you're after by doing this:

if (gettype($field) == 'integer' || gettype($field) == 'double') {
    $field = strval($field); // Change $field to string if it's a numeric type
}

Here's the full code with it added

function arrayToCsv( array $fields, $delimiter = ';', $enclosure = '"', $encloseAll = false, $nullToMysqlNull = false ) {
    $delimiter_esc = preg_quote($delimiter, '/');
    $enclosure_esc = preg_quote($enclosure, '/');

    $outputString = "";
    foreach($fields as $tempFields) {
        $output = array();
        foreach ( $tempFields as $field ) {
            // ADDITIONS BEGIN HERE
            if (gettype($field) == 'integer' || gettype($field) == 'double') {
                $field = strval($field); // Change $field to string if it's a numeric type
            }
            // ADDITIONS END HERE
            if ($field === null && $nullToMysqlNull) {
                $output[] = 'NULL';
                continue;
            }

            // Enclose fields containing $delimiter, $enclosure or whitespace
            if ( $encloseAll || preg_match( "/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field ) ) {
                $field = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure;
            }
            $output[] = $field." ";
        }
        $outputString .= implode( $delimiter, $output )."\r\n";
    }
    return $outputString; 
}
Wailful answered 19/9, 2014 at 16:36 Comment(0)
O
0

Here is a solution that is a little more general purpose. I was actually looking for a way to make string lists for SQL bulk inserts. The code would look like this:

foreach ($rows as $row) {
    $string = toDelimitedString($row);
    // Now append it to a file, add line break, whatever the need may be
}

And here is the useful function that I ended up adding to my tookit:

/**
 * Convert an array of strings to a delimited string. This function supports CSV as well as SQL output since
 * the quote character is customisable and the escaping behaviour is the same for CSV and SQL.
 *
 * Tests:
 *  echo toDelimitedString([], ',', '\'', true) . "\n";
 *  echo toDelimitedString(['A'], ',', '\'', true) . "\n";
 *  echo toDelimitedString(['A', 'B'], ',', '\'', true) . "\n";
 *  echo toDelimitedString(['A', 'B\'C'], ',', '\'', true) . "\n";
 *  echo toDelimitedString([], ',', '\'', true) . "\n";
 *  echo toDelimitedString(['A'], ',', '"', true) . "\n";
 *  echo toDelimitedString(['A', 'B'], ',', '"', true) . "\n";
 *  echo toDelimitedString(['A', 'B"C'], ',', '"', true) . "\n";
 *
 * Outputs:
 *  <Empty String>
 *  'A'
 *  'A','B'
 *  'A','B''C'
 *  <Empty String>
 *  "A"
 *  "A","B"
 *  "A","B""C"
 *
 * @param array $array A one-dimensional array of string literals
 * @param string $delimiter The character to separate string parts
 * @param string $quoteChar The optional quote character to surround strings with
 * @param bool $escape Flag to indicate whether instances of the quote character should be escaped
 * @return string
 */
function toDelimitedString(array $array, string $delimiter = ',', string $quoteChar = '"', bool $escape = true)
{
    // Escape the quote character, since it is somewhat expensive it can be suppressed
    if ($escape && !empty($quoteChar)) {
        $array = str_replace($quoteChar, $quoteChar . $quoteChar, $array);
    }

    // Put quotes and commas between all the values
    $values = implode($array, $quoteChar . $delimiter . $quoteChar);

    // Put first and last quote around the list, but only if it is not empty
    if (strlen($values) > 0) {
        $values = $quoteChar . $values . $quoteChar;
    }

    return $values;
}
Owings answered 26/7, 2018 at 12:24 Comment(0)
S
0

Just add and call the function below:

function FromCells($cells, $delimiter = ',', $enclosure = '"', $eol = "\n") :string {
        if(empty($cells)) return "";
        $fstream = fopen('php://temp', 'r+b');
        foreach ($cells as $fields) fputcsv($fstream, $fields, $delimiter, $enclosure, "\\", $eol);
        rewind($fstream);
        $data = rtrim(stream_get_contents($fstream), $eol);
        fclose($fstream);
        return $data;
}

Enjoy...

Sidonnie answered 15/7, 2024 at 6:39 Comment(0)
S
-1

This implementation does not use file pointers, shouldn't inadvertently modify any data passed to it, and only escapes as required, analogous to fputcsv() (but without the $escape_char nonsense):

function str_putcsv(array $fields, string $delimiter = ',', string $enclosure = '"') {
    $escs = [];
    foreach ($fields as $field) {
        $esc = (string) $field;
        if (
            false !== strpos($esc, $delimiter)
            || false !== strpos($esc, $enclosure)
        ) {
            $esc = $enclosure . strtr($esc, ["$enclosure" => "$enclosure$enclosure"]) . $enclosure;
        }
        $escs[] = $esc;
    }
    return implode($delimiter, $escs) . PHP_EOL;
}

Drop the string type declarations if your PHP version doesn't support them.

Sexism answered 16/3, 2021 at 4:54 Comment(0)
S
-2

The function above is not exactly right cause it considers \n like an element, which is not what we want as each line must be only separated by \n. So a more efficient code would be:

function array2csv($array, $delimiter = "\n") {
    $csv = array();
    foreach ($array as $item=>$val) 
    {
        if (is_array($val)) 
        { 
            $csv[] = $this->array2csv($val, ";");
        } 
        else 
        {
            $csv[] = $val;
        }
    }
    return implode($delimiter, $csv);
}
Spreader answered 22/5, 2018 at 9:37 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.