WordPress からテーマのテンプレートを使って CSV を書き出す
カテゴリー: WordPress
この記事は2020年7月11日に書かれたものです。情報が古い可能性がありますのでご注意ください。
WordPress からカスタム投稿タイプの投稿データとそれに関連するデータを CSV で出力したい案件があり、テーマの中のテンプレートを使って実現してみました。
投稿データを CSV で出力できるプラグインはあるようですが、今回一定の条件で絞り込んだり、Advanced Custom Fields の「投稿オブジェクト」カスタムフィールドで紐付けた、別のカスタム投稿タイプの投稿データを一緒に出力する必要があったため、特定のページのテンプレートを作成する要領で実現できないかと考えました。
7年くらい前まで Movable Type を使っていましたが、Movable Type のテンプレートは静的ファイルを書き出すので、書き出すファイル名と拡張子を指定すれば、CSV などのテキストファイルを書き出すことも、CSS や JavaScript のファイルに MT タグを使って、セレクタや値を代入したり変数をループで処理したりすることができました。
一方、WordPress のテンプレートは動的に Web ページを表示するものなので、Movable Type のように簡単には行きません。
でも、以前 WordPress に FullCalendar を組み込んだ際、カレンダーに投稿データを読み込むための JSON 形式のファイルをテンプレートを使って作成したり、同じように Google Map に投稿データからマーカーを生成するための XML 形式のファイルをテンプレートを使って作成した経験がありましたので、まずは同様の方法で CSV 形式のファイルを作成してみました。
まず、CSV 用の固定ページを作成します。タイトルは何でもよく、本文は空で、任意のスラッグを設定します。ここでは仮に「custom-csv」とします。
続いて、この固定ページ用のテンプレートを作成します。この固定ページに適用するため、ファイル名を「page-custom-csv.php」とし、通常のテンプレートを記述する要領で、CSV として書き出すためのコードを書きます。
例として、カスタム投稿タイプの投稿のタイトルと、「フィールド1」から「フィールド5」まで、5つのカスタムフィールドの値を書き出すものとします。冒頭の絞り込みや「投稿オブジェクト」の出力は CSV の出力と直接関係ないのでここでは触れません。
また、「フィールド5」のカスタムフィールドはチェックボックスとします。チェックボックスはそのまま書き出すと複数の値が「,」で区切られ、CSV の区切り文字と同じになるので、ここでは「/」で区切ることにします。
<?php
$csv = null;
$args = array(
'post_type' => 'custom-post',
'post_status' => 'publish',
'posts_per_page' => -1
);
$my_query = new WP_Query( $args );
if ( $my_query -> have_posts() ):
$csv = 'タイトル,フィールド1,フィールド2,フィールド3,フィールド4,フィールド5';
while ( $my_query -> have_posts() ): $my_query -> the_post();
$csv .= get_the_title(). ',';
$csv .= get_field('custom-field1'). ',';
$csv .= get_field('custom-field2'). ',';
$csv .= get_field('custom-field3'). ',';
$csv .= get_field('custom-field4'). ',';
$csv .= implode('/', get_field('custom-field5')). ',';
$csv .= "\n";
endwhile;
endif;
wp_reset_postdata();
echo $csv;
?>
とりあえず、これで固定ページ「custom-csv」を表示すると、次のような CSV 形式のデータが表示されます。(ブラウザ上では1行で表示されますが、ソースコード上では改行されます。)
タイトル,フィールド1,フィールド2,フィール3,フィールド4,フィールド5
タイトルA,フィールドデータ1A,フィールドデータ2A,フィールドデータ3A,フィールドデータ4A,フィールドデータ5A
タイトルB,フィールドデータ1B,フィールドデータ2B,フィールドデータ3B,フィールドデータ4B,フィールドデータ5B
タイトルC,フィールドデータ1C,フィールドデータ2C,フィールドデータ3C,フィールドデータ4C,フィールドデータ5C
しかし、これは CSV 形式で表示しているだけなので、このままでは CSV ファイルとして扱うことができません。
以前同様の方法で作成した FullCalendar 用の JSON 形式のデータや Google Map 用の XML 形式のデータは、同じテーマの中で使用するのでこのままでよかったのですが、CSV の場合はダウンロードして Excel 等で利用できるようにする必要があります。
表示されたソースコードをコピーしてテキストエディタに貼り付け、.csv で保存すれば扱うことができますが、Windows の Excel で開くためには文字コードも変換しなければなりませんし、そんな面倒なことはできませんので。
そこで、文字コードを UTF-8 から Shift-JIS に変換し、CSV ファイルとしてダウンロードできるようにします。「php csv ダウンロード」でググってみたらたくさんのヒントがありました。先のコードの先頭に HTTP ヘッダを3行追加し、最後の出力処理で文字コードを変換します。
<?php
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=custom.csv');
header('Content-Transfer-Encoding: binary');
$csv = null;
$args = array(
'post_type' => 'custom-post',
'post_status' => 'publish',
'posts_per_page' => -1
);
$my_query = new WP_Query( $args );
if ( $my_query -> have_posts() ):
$csv = 'タイトル,フィールド1,フィールド2,フィールド3,フィールド4,フィールド5';
while ( $my_query -> have_posts() ): $my_query -> the_post();
$csv .= get_the_title(). ',';
$csv .= get_field('custom-field1'). ',';
$csv .= get_field('custom-field2'). ',';
$csv .= get_field('custom-field3'). ',';
$csv .= get_field('custom-field4'). ',';
$csv .= implode('/', get_field('custom-field5')). ',';
$csv .= "\n";
endwhile;
endif;
wp_reset_postdata();
echo mb_convert_encoding($csv, 'SJIS', 'UTF-8');
return;
?>
HTTPヘッダの2行目の filename=custom.csv
でダウンロードする際のファイル名を設定しています。
これで、任意のページに固定ページ「custom-csv」へのリンクを設置すれば、 そのリンクから custom.csv をダウンロードするダイアログが表示されます。