【PHP】CSV出力したいのにheader()関数が効かない
環境
やりたかったこと
PHPでCSVを出力する機能を作っていて、レスポンスヘッダーを下記のように設定したかった。
Content-Disposition: attachment; filename=ファイル名.csv Content-Type: text/csv
課題
下記のメソッドを使ってレスポンスしたのに、 header()
で設定したはずのが反映されていない。
使用した関数
<?php /** * CSVダウンロード * * @param string $file_name * @param array $header * @param array $csv_list * @return void */ public static function csvDownload($file_name, $header, $csv_list) { // 出力バッファをopen $stream = fopen('php://output', 'w'); // 文字化け対策 mb_convert_variables('SJIS-win', 'UTF-8', $header); // 列名を記入 fputcsv($stream, $header); // 2行目以降を1行ずつストリームへ記入 foreach ($csv_list as $line) { mb_convert_variables('SJIS-win', 'UTF-8', $line); fputcsv($stream, $line); } fclose($stream); // ファイルダウンロードさせるためにヘッダーを調整 header("Content-Type: text/csv"); header("Content-Disposition: attachment; filename=$file_name"); readfile($file_name); exit; }
Postmanで確認したレスポンスヘッダ
解決策
先程のメソッドで、 header()
関数を使う順番を最初に持ってきた
<?php /** * CSVダウンロード * * @param string $file_name * @param array $header * @param array $csv_list * @return void */ public static function csvDownload($file_name, $header, $csv_list) { // ファイルダウンロードさせるためにヘッダーを調整 header("Content-Type: text/csv"); header("Content-Disposition: attachment; filename=$file_name"); // 出力バッファをopen $stream = fopen('php://output', 'w'); // 文字化け対策 mb_convert_variables('SJIS-win', 'UTF-8', $header); // 列名を記入 fputcsv($stream, $header); // 2行目以降を1行ずつストリームへ記入 foreach ($csv_list as $line) { mb_convert_variables('SJIS-win', 'UTF-8', $line); fputcsv($stream, $line); } fclose($stream); readfile($file_name); exit;; }
すると、想定通りにレスポンスヘッダに反映されていた。
公式にも記載の通り、メソッド内でも先に書くようにということか?
覚えておいて頂きたいのは、header() 関数は、 通常の HTML タグまたは PHP からの出力にかかわらず、すべての実際の 出力の前にコールする必要があることです。 https://www.php.net/manual/ja/function.header