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);
Community
  • 1
  • 1
chongzixin
  • 1,951
  • 4
  • 28
  • 55
  • 2
    Why are you going through all this? Can't you just serve a CSV file direct from the server as a download? –  Oct 28 '13 at 03:15
  • 1
    Agreed with Mike W. Usually when you are blending PHP code into Javascript code, you are over-complicating something. – teynon Oct 28 '13 at 03:17
  • Hmmm I never thought of that, maybe I will give that a try. Any advice or pointers on that will be very greatly appreciated! – chongzixin Oct 28 '13 at 03:44
  • I found some resources stating the use of `fputcsv`, but I am afraid I dont have ready access to my server to allow permissions for PHP to write files. Is there some workaround? – chongzixin Oct 28 '13 at 03:48
  • @user1258600 How do you upload PHP files? – teynon Oct 28 '13 at 04:13
  • @user1258600 See edit to my answer for how to output without writing a file. – teynon Oct 28 '13 at 04:17

2 Answers2

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);
    }
teynon
  • 7,540
  • 10
  • 63
  • 106
  • Thanks so much for your answer. So in order to allow that as a downloadable CSV I should put the above fputcsv into its own php file and add headers to it like mentioned in this link? (http://stackoverflow.com/questions/15769732/write-to-php-output-buffer-and-then-download-csv-from-buffer) – chongzixin Oct 28 '13 at 06:27
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);
}
jerdiggity
  • 3,655
  • 1
  • 29
  • 41
  • If the OP is handling as large a data set as suggested by the Javascript stack exhausted message, there is a good chance that using that array walk with the function call is going to add a noticeable lag time. – teynon Oct 28 '13 at 05:49