MySQLのデータをCSVでダウンロードする

MySQLのデータベーステーブルの情報をPHPを使ってダウンロードします。驚きなのがこのご時世にCSVダウンロードのコマンドとかがないみたいです。SQL文は何となくあったのですが、全然通らなかったので私がダメなのかもわかりません。
HTMLでフォームとかアンカーを作成して、例えば下記のコードをdl.phpとかにしてスクリプトを叩くとCSVファイルがダウンロードできます。

手順としては、

  1. ダウンロード用のヘッダをつける
  2. MySQLにアクセスしてseletする
  3. 全データをCSVフォーマットにしたがって書きだす

という流れになります。肝になる部分はいくつかあるのですが、ダウンロードさせるということでヘッダをつけてあげないとダメです。
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=output.csv");

このヘッダはこのままでよいのですが、HTMLのコードとして<?php ?>で囲んで実行すると2行分の無駄な改行がCSVに入ってしまうので最後に削除するようなコードを書き加えるか、またはヘッダそのものを1つの<?php ?>内に入れてやらないとダメです。またこのヘッダではダウンロードするファイル名そのものを指定してあげる必要もあります。

次にデータベースにコネクトしてselect文でデータを取得します。このselect文を変えてあげればCSVとして抽出するデータ量を調節できます。それからCSVを書き出すわけですが、問題になるのがテキストなどの改行です。CSVは改行コードデータのレコードの終端とみなすので、Longtext内の改行がCSV内で改行してしまいます。そのような時には"ダブルクォートで囲ってあげないとダメです。また、テキスト内にすでにダブルクォートがある時には何らかの置換をしてあげないとこれまたダメなのです。下記の例では全角のダブルクォートと全角のシングルクォートに置換してます。CSVはたいていの場合、エクセルで開くとかが目的だったりするので、取り急ぎこれでいいかと思います。(下記の例でもUTF-8のDBデータをSHIFT_JISに文字コード変換しています。)仕様に従っていろいろやりようはあるかと思います。データはヘッダを出力しているので、print文で書き込みができますので、バーっと書きだしてください。開発デバックはヘッダ部分をコメントアウトするとブラウザーに表示されるので楽です。

ということで、注意点は、

  • DBデータの文字コード・出力するCSVの文字コード
  • 抽出するデータの調整(日付やシリアル、レコードの数や種類など)
  • テキストレコード内の改行問題とダブルクォート(シングルクォート)

ということになります。
<?php
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=output.csv");

$db_host = "localhost";
$db_user = "DBUSER";
$db_passwd = "PPASSWD";
$db_name = "DBNAME";
$sql = "SELECT * FROM wp_posts";

$db = mysql_connect($db_host,$db_user,$db_passwd);
mysql_query("set names utf8");
mysql_select_db($db_name,$db);
$result = mysql_query($sql,$db);
for($i=0; $i<mysql_num_fields($result); $i++){
print (mb_convert_encoding(mysql_field_name($result,$i),'SJIS', 'UTF-8').",");
}
print("¥n");
for($j=0 ; $j<mysql_num_rows($result); $j++) {
for($k=0; $k<mysql_num_fields($result); $k++) {
$str = mysql_result($result,$j,$k);
print (mb_convert_encoding($str,'SJIS', 'UTF-8').",");
}
print("¥n");
}
mysql_close($db);
?>