60 lines
1.5 KiB
PHP
60 lines
1.5 KiB
PHP
<?php
|
|
|
|
namespace App\Exports;
|
|
|
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
|
|
class CsvExport
|
|
{
|
|
/**
|
|
* @param array<int, string> $headers
|
|
* @param array<int, array<int, mixed>> $rows
|
|
*/
|
|
public static function download(string $filename, array $headers, array $rows): StreamedResponse
|
|
{
|
|
return response()->streamDownload(function () use ($headers, $rows): void {
|
|
$handle = fopen('php://output', 'wb');
|
|
|
|
if ($handle === false) {
|
|
return;
|
|
}
|
|
|
|
// UTF-8 BOM improves Russian text rendering in Excel.
|
|
fwrite($handle, "\xEF\xBB\xBF");
|
|
|
|
fputcsv($handle, self::normalizeRow($headers), ';');
|
|
|
|
foreach ($rows as $row) {
|
|
fputcsv($handle, self::normalizeRow($row), ';');
|
|
}
|
|
|
|
fclose($handle);
|
|
}, $filename, [
|
|
'Content-Type' => 'text/csv; charset=UTF-8',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @param array<int, mixed> $row
|
|
* @return array<int, mixed>
|
|
*/
|
|
private static function normalizeRow(array $row): array
|
|
{
|
|
return array_map(static function (mixed $value): mixed {
|
|
if ($value === null) {
|
|
return '';
|
|
}
|
|
|
|
if (is_string($value)) {
|
|
return str_replace(["\r\n", "\r"], "\n", $value);
|
|
}
|
|
|
|
if (is_bool($value)) {
|
|
return $value ? '1' : '0';
|
|
}
|
|
|
|
return $value;
|
|
}, $row);
|
|
}
|
|
}
|