PHPでCSVをダウンロードする方法(一時ファイルを作らない)

kmaebashi.comのサーバ移転に伴い、掲示板のデータも移行したわけですが、その際、PHP + MySQLで作った旧掲示板のデータをCSVにしてダウンロードする、という作業を行いました。
当方PHPは2004年だか2005年だかに旧掲示板を作って以来、PHPはほとんど使ってなくてすっかり忘れておりますが、PHPCSVをダウンロードするなんてよくある話だろうから、ちょっとGoogle検索すればサンプルが山ほど出てくるだろう、と思って検索してみたところ、サンプルは山ほど出てきたものの、どれもこれも「fputcsv()」というPHPの組み込み関数を使ってCSVを一時ファイルに書き出し、それをダウンロードさせている。いや別に一時ファイル作ってもよいのだけれど、こんなの作らなくてもできるだろストリームにダブルクオートだけ変換した文字列を吐くだけだろ、ということで、使わない形で作ったものをここに書き残しておきます。うちの掲示板のテーブル設計に依存したものなので、その辺は適当に読みかえてください。

  • 2005年から使っているものなのでDBへのアクセス方法が古いことはまあ大目に見てください。
  • boardidがtestbbsの投稿は、テスト掲示板への投稿で、広告だらけだったので除外しました。
  • DBの各列をいったんすべて変数に入れているのは――なぜだろう? 直接$row["serialid"]とか書いてもよさそうですが。数か月前の意図が思い出せない……
  • DBはEUCだったので、UTF8に変換してダウンロードしよう、と思ったのですが、「①」のような機種依存文字が化けるようで、結局EUCのままダウンロードしてクライアントのWindows用エディタ(xyzzy)でUTF8に変換しました。
<?php
require 'connect_db.php';

$sql_str = "select * from message where boardid <> 'testbbs' order by boardid, serialid";
$result = mysql_query($sql_str) or die('SQLエラー'.$sql_str);

header("Content-Type: application/octet-stream");
header('Content-Disposition: attachment; filename="bbs.csv"');

while ($row = mysql_fetch_assoc($result)) {
  $serialid=$row["serialid"];
  $boardid=$row["boardid"];
  $date = $row["posteddate"];
  $name = $row["name"];
  $mailaddress = $row["mailaddress"];
  $url = $row["url"];
  $subject = $row["subject"];
  $message = $row["message"];
  $altermessage = $row["altermessage"];
  $password = $row["password"];
  $salt = $row["salt"];
  $preformatted = $row["preformatted"];
  $deleted = $row["deleted"];
  $admindeleted = $row["admindeleted"];
  $parent = $row["parent"];
  $top = $row["top"];
  $ipaddress = $row["ipaddress"];
  $remotehost = $row["remotehost"];
  $useragent = $row["useragent"];

  echo $serialid . ",";
  echo $boardid . ",";
  echo $date . ",";
  echo quote_field($name). ",";
  echo quote_field($mailaddress). ",";
  echo quote_field($url). ",";
  echo quote_field($subject). ",";
  echo quote_field($message). ",";
  echo quote_field($altermessage). ",";
  echo quote_field($password). ",";
  echo quote_field($salt). ",";
  echo $preformatted. ",";
  echo $deleted. ",";
  echo $admindeleted. ",";
  echo $parent. ",";
  echo $top. ",";
  echo $ipaddress. ",";
  echo $remotehost. ",";
  echo $useragent. "\r\n";
}

function quote_field($src) {
//  $replaced = mb_convert_encoding($src, "utf-8", "euc-JP-win");
  $replaced = str_replace('"', '""', $src);

  return '"' . $replaced . '"';
}
?>