$item) { $csv .= self::getRow($headers, $item); } return $csv; } private static function collectHeaders(array $items): array { $allHeaders = []; foreach ($items as $item) { $headers = Hash::flatten($item); foreach ($headers as $head => $value) { if (str_starts_with($head, '_')) { continue; } if (is_array($value) && empty($value)) { continue; } $allHeaders[$head] = 1; } } return array_keys($allHeaders); } private static function getRow(array $headers, array $item): string { $tmp = []; foreach ($headers as $header) { $value = Hash::get($item, $header); if (!isset($value)) { $value = ''; } if (is_bool($value)) { $value = !empty($value) ? '1' : '0'; } $tmp[] = '"' . $value . '"'; } $row = implode(',', $tmp) . PHP_EOL; return $row; } private static function quoteArray(array $arr): array { return array_map(function($item) { return '"' . $item . '"'; }, $arr); } private static function array_is_list(array $arr): bool { if ($arr === []) { return true; } return array_keys($arr) === range(0, count($arr) - 1); } }