<?php
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="' . $filename . '.csv"');

$batchCount = 100;
$csvHeaders = array_keys($headers);
$queryHeaders = array_values($headers);

$output = fopen('php://output', 'w');
fputcsv($output, $csvHeaders);

$queryCount = $query->select($countColumn)->count();
$numOfBatches = ceil($queryCount / $batchCount);

for ($i = 0; $i < $numOfBatches; $i++) {
    $rows = $query->select($queryHeaders)->skip($i * $batchCount)->take($batchCount)->get()->toArray();
    foreach ($rows as $row) {
        $row = !is_array($row) ? array_values((array) $row) : $row;
        array_walk($row, function (&$item) {
            $item = is_array($item) ? implode('##', $item) : $item;
        });

        fputcsv($output, $row);
    }
}
