質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
WordPress

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

1回答

2653閲覧

WordPressの自作プラグインでのCSVダウンロード機能

mikeko0901

総合スコア227

WordPress

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2022/02/23 13:43

WordPressの管理画面で、独自追加したテーブルを一覧で表示したり編集したりする機能をプラグインを作成して実装しています。

そこで、CSVダウンロード機能をつけたいのですがうまくできません。アドバイスいただけますと幸いです。

(現在)
イメージ説明

ダウンロードボタンをクリックすると

イメージ説明

何も起きません‥‥

コード

wp-content>plugins>test-crud-plugin>test-crud-plugin.php

<?php /* Plugin Name: TestCrudPlugin Plugin URI: Description: 試験用のアプリ Version: 1.0 Author: Ito */ require_once(plugin_dir_path(__FILE__) . 'test-crud-util.php'); require_once(plugin_dir_path(__FILE__) . 'test-crud-edit.php'); add_action('admin_menu', 'testCrudPluginMenu'); /* 管理画面呼び出し manage_options→administratorにすると権限でアクセスできなくなる*/ function testCrudPluginMenu() { add_menu_page('テストメニューだよ','申込一覧','manage_options', 'test-crud-plugin', 'testCrudPluginPage' , 'dashicons-database'); } /* 管理画面表示部 */ function testCrudPluginPage() { //editページ if(isset($_GET["edit"])) { testCrudEditPage(); } else if(isset($_GET["download"])) { //★ダウンロードボタンがクリックされた時の処理 add_action('init', function() { global $wpdb; $sql = "SELECT * FROM wp_test;"; $records = $wpdb->get_results($sql, ARRAY_A); $data = []; $i = 0; $data[$i] = [ //ヘッダーをセット "id", "name", "email", "日時" ]; foreach($records as $record) { $i++; $data[$i][] = $record["id"]; $data[$i][] = $record["name"]; $data[$i][] = $record["email"]; $data[$i][] = $record["created_at"]; } $file_name = "order.csv"; $fp = fopen('php://output', 'w'); header('Content-Type: application/octet-stream'); header("Content-Disposition: attachment; filename={$file_name}"); header('Content-Transfer-Encoding: binary'); // UTF-8からSJIS-winへ変換するフィルター stream_filter_append($fp, 'convert.iconv.UTF-8/CP932//TRANSLIT', STREAM_FILTER_WRITE); foreach ($data as $row) { fputcsv($fp, $row, ',', '"'); } fclose($fp); }); } else { //リストページ //wp_testテーブルの商品数を取得 global $wpdb; $sql = "SELECT * FROM wp_test;"; $records = $wpdb->get_results($sql, ARRAY_A); ?> <div class="wrap"> <h2>申込一覧</h2> <div class="postbox "> <button>新規追加</button> <?php print($_REQUEST['page']); ?> <button onclick="location.href='?page=test-crud-plugin'">申込一覧TOP</button> <button onclick="location.href='?page=test-crud-plugin&download'">ダウンロード</button> <div class="inside"> <div class="main"> <table class="wp-list-table widefat fixed striped table-view-list posts"> <thead> <tr> <th></th> <th>id</th> <th>お名前</th> <th>メール</th> <th>日時</th> </tr> </thead> <tbody> <?php if($records): foreach($records as $record): ?> <tr> <td><button onclick="location.href='?page=test-crud-plugin&edit=<?php print($record['id']); ?>'">編集</button></td> <td><?php print($record['id']); ?></td> <td><?php print($record['name']); ?></td> <td><?php print($record['email']); ?></td> <td><?php print($record['created_at']); ?></td> </tr> <?php endforeach; endif; ?> </tbody> </table> </div> </div> </div> </div> <?php } }

admin.php?page=test-crud-plugin&download
のように、パラメータに「download」がついた時はダウンロードさせる
というようにしています。
最初、

Cannot modify header information - headers already sent by

というエラーが出たので、CSVダウンロードの処理を、

add_action('init', function() {

で囲みました。
そうしましたら、headers already sent のエラーは出なくなりましたが、
キャプチャのようになりました。。

WordPressの管理画面内ではなく、通常のPHPプログラムとしては問題なくCSV出力できているものを元にして実装しています。

何卒、よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

  1. add_menu_pageのcallbackは出力開始よりずっと後に実行されるのでheaderの送出はできません
  2. admin_menuはinitより後に発火されるのでadmin_menuでinitにadd_actionしても実行されることがありません

add_menu_pageのcallbackでCSVの出力をしようとする仕様を見直しましょう。
wp ajaxを使うのが最も簡単だと思います。


補足

wp ajaxはajaxを使わずに直接wp-admin/admin-ajax.php?action=...を叩いて使うこともできます、
wp ajaxの処理のタイミングではヘッダの送出はされていないので、任意のContentTypeのヘッダの送出ができます。

またwp ajaxは処理の登録時にwp_ajax_nopriv_*の方は登録しないようにしておけば、ログインユーザーしか利用できません。

本来の使い方ではないにしろ、この手の管理画面からファイルをダウンロードさせる際の簡単な方法です。

投稿2022/02/24 01:26

編集2022/02/24 02:32
KazuhiroHatano

総合スコア7804

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mikeko0901

2022/02/24 09:17

承知しました! wp-ajaxは編集機能実装のところでテストしましたので、そちらでやってみます! ありがとうございました。
mikeko0901

2022/02/24 14:35

wp-ajaxを用いて以下のように実装しました。無事ダウンロードできました。 wp-content>plugins>test-crud-plugin>test-crud-plugin.php ``` <?php /* Plugin Name: TestCrudPlugin Plugin URI: Description: 試験用のアプリ Version: 1.0 Author: AyakoIto */ require_once(plugin_dir_path(__FILE__) . 'test-crud-util.php'); require_once(plugin_dir_path(__FILE__) . 'test-crud-edit.php'); add_action('admin_menu', 'testCrudPluginMenu'); /* 管理画面呼び出し manage_options→administratorにすると権限でアクセスできなくなる*/ function testCrudPluginMenu() { add_menu_page('テストメニューだよ','申込一覧','manage_options', 'test-crud-plugin', 'testCrudPluginPage' , 'dashicons-database'); } /* 管理画面表示部 */ function testCrudPluginPage() { //editページ if(isset($_GET["edit"])) { testCrudEditPage(); } else { //リストページ testCrudListPage(); } } //リストページ表示用の関数 function testCrudListPage() { //wp_testテーブルの商品数を取得 global $wpdb; $sql = "SELECT * FROM wp_test;"; $records = $wpdb->get_results($sql, ARRAY_A); ?> <div class="wrap"> <h2>申込一覧</h2> <div class="postbox "> <button>新規追加</button> <?php print($_REQUEST['page']); ?> <button onclick="location.href='?page=test-crud-plugin'">申込一覧TOP</button> <button id="download">ダウンロード</button> <div class="inside"> <div class="main"> <table class="wp-list-table widefat fixed striped table-view-list posts"> <thead> <tr> <th></th> <th>id</th> <th>お名前</th> <th>メール</th> <th>日時</th> </tr> </thead> <tbody> <?php if($records): foreach($records as $record): ?> <tr> <td><button onclick="location.href='?page=test-crud-plugin&edit=<?php print($record['id']); ?>'">編集</button></td> <td><?php print($record['id']); ?></td> <td><?php print($record['name']); ?></td> <td><?php print($record['email']); ?></td> <td><?php print($record['created_at']); ?></td> </tr> <?php endforeach; endif; ?> </tbody> </table> </div> </div> </div> </div> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script> $("#download").click(function(){ $.ajax({ type: "POST", dataType: "json", url: "admin-ajax.php?action=list_dl_ajax", data:{ }, success:function(data) { //data_arr = JSON.parse(data); console.log(data); //作った二次元配列をCSV文字列に直す。 let csv_string = ""; for (let d of data) { csv_string += d.join(","); csv_string += '\r\n'; } //ファイル名の指定 let file_name = "test.csv"; //エクセルの文字化け対策 var bom = new Uint8Array([0xEF, 0xBB, 0xBF]); //CSVのバイナリデータを作る let blob = new Blob([bom, csv_string], {type: "text/csv"}); let uri = URL.createObjectURL(blob); //リンクタグを作る let link = document.createElement("a"); link.download = file_name; link.href = uri; //作ったリンクタグをクリックさせる document.body.appendChild(link); link.click(); //クリックしたら即リンクタグを消す document.body.removeChild(link); delete link; }, error:function(XMLHttpRequest, textStatus, errorThrown) { } }); }); </script> <?php } //CSVダウンロード用ajax(データ取得部分) function list_dl_ajax() { global $wpdb; $sql = "SELECT * FROM wp_test;"; $records = $wpdb->get_results($sql, ARRAY_A); $data = []; $i = 0; $data[$i] = [ //ヘッダーをセット "id", "name", "email", "日時" ]; foreach($records as $record) { $i++; $data[$i][] = $record["id"]; $data[$i][] = $record["name"]; $data[$i][] = $record["email"]; $data[$i][] = $record["created_at"]; } echo json_encode($data); die(); //これがないと戻り値に0がつく } add_action('wp_ajax_list_dl_ajax', 'list_dl_ajax'); ```
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問