1

I am trying to create a data analytics portal which allows me to export one of my tables as CSV. The problem I have now is that when a user selects a huge range of data, it fails because it has reached the maximum stack size for Javascript variables available to my browser. (As explained here). The solution is to split them into smaller Javascript array chunks and then concatenate them again later.

My problem

I have a big PHP array (of variable size because I wont know what range the user selects) and I need to split them into a variable number of Javascript arrays and then concatenate them again later. How can I achieve that?

My code currently looks like that

<?php 
$array2 = getAllRawData($startDate, $endDate, $merchantID);
array_unshift($array2, ...TO ADD HEADER TO CSV....));
?>

// I am thinking some magic is supposed to happen here that splits my PHP array into smaller parts, assign them to javascript arrays and then concatenate them together into items2.

var items2 = <?php echo json_encode($array2);?>; // this is what I currently do but fails when the date range gets too wide.

var jsonObject2 = JSON.stringify(items2);
var csv2 = ConvertToCSV(jsonObject2);

a=document.createElement('a');
a.textContent='Download Raw Waiting Time Report';
a.download="RawWaitTime.csv";
a.href='data:text/csv;charset=utf-8,'+escape(csv2);
document.body.appendChild(a);
4

2 回答 2

4

As stated in comments, it is probably best to build the CSV in PHP. However, to answer the question of how to split the arrays for Javascript, you could use the window container. However, this implies that objects may not have the same Javascript limit or that the post you link to is inaccurate. (I'm not sure because I haven't seen nor tested this limit error.)

http://jsfiddle.net/TYwY8/7/

<script>
var Array0 = ["1", "2", "3"];
var Array1 = ["4", "5", "6"];
var Array2 = ["7", "8", "9"];
var Array3 = ["10", "11", "12"];
var Array4 = ["13", "14", "15"];
var ArrayCount = 5;

for (var x = 0; x < ArrayCount; x++) {
    console.log(window["Array" + x]);
}

</script>

You could slice those arrays via PHP like this: (untested)

<?php

    $limit = 10000;
    $arrayCount = count($array) % limit;

    $offset = 0;
    for ($x = 0; $arrayCount; $x++) {
        echo "var MyArray{$x} = [" . implode(",", array_slice($array, $offset, $limit)) . "];";
        $offset += $limit;
    }

To use fputcsv without writing a file:

<?php

    $file = fopen("php://output", "w");

    $array = [  [ "1", "2", "3" ], [ "4", "5", "6" ], [ "7", "8", "9" ] ];

    foreach ($array as $value) {
        fputcsv($file, $value);
    }
于 2013-10-28T03:36:11.280 回答
0

Good answer by Tom. Here's another solution that should work also for producing the CSV output:

<?php
$array2 = getAllRawData($startDate, $endDate, $merchantID);
// This may or may not be necessary, depending on if you have
// objects mixed in with the value of $array2
$array2 = unserialize(serialize(json_decode(json_encode($array2), 1)));
print create_csv($array2);

function create_csv($input) {
    $output = fopen("php://output", 'w');
    function create_csv_handler(&$values, $key, $fh) {
        fputcsv($fh, $values, ',', '"');
    }
    array_walk($input, 'create_csv_handler', $output);
    fclose($output);
}
于 2013-10-28T04:23:02.953 回答