エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年1月29日 at 16:28

フォーラムの皆さま

いつも大変お世話になっております。
外部フォームブロックに、Expressエンティティを選択できる
リストボックスを作成し、選択したエンティティをCSVファイル
としてダウンロードしたいと考えております。

通常の、ダッシュボードからエクスプレスエンティティ詳細画面
にアクセスし、「CSVデータダウンロード」を実行することと同じ
機能を外部フォームで実現したいと思いますが、
可能でしょうか?

現在考えておりますのは、
・外部フォームのリストボックスのvalue にエンティティ名を設定
・submit 実行時、Express エンティティ名(value)を postして
 コントローラ側へ渡す
・コントローラで受け取ったエンティティ名を引数にして、
 Expressエンティティのデータを取得して配列に格納
・CSVファイルとしてサーバ上に出力➡ダウンロード
という手順です。

ぜひご教示賜ればと存じます。
どうぞよろしくお願い申し上げます。

# concrete5 Version
Core Version - 8.5.4
Version Installed - 8.5.4
Database Version - 20200609145307

# Database Information
Version: 5.1.73
SQL Mode:

# concrete5 Packages
CSV User Import & Export (0.1.1), Honest Websites Back To Top (1.1.0), Login/Logout Link (1.0), Login Page Background (0.9.1), Manual Nav (2.3.3), Migration Tool (0.9.1)

# concrete5 Overrides
blocks/external_form/form/controller/tkp_menu.php, blocks/external_form/form/controller/enq_a.php, blocks/external_form/form/controller/enq_b.php, blocks/external_form/form/controller/enq_c.php, blocks/external_form/form/controller/shukai.php, blocks/external_form/form/controller/enqopt.php, blocks/external_form/form/controller/emenu.php, blocks/external_form/form/controller/mailtmp.php, blocks/external_form/form/controller/csvdwn.php, blocks/external_form/form/controller, blocks/external_form/form/tkp_menu.php, blocks/external_form/form/enq_a.php, blocks/external_form/form/enq_b.php, blocks/external_form/form/enq_c.php, blocks/external_form/form/shukai.php, blocks/external_form/form/enqopt.php, blocks/external_form/form/emenu.php, blocks/external_form/form/mailtmp.php, blocks/external_form/form/csvdwn.php, blocks/external_form/form, blocks/external_form, mail/mail_send_hyoka_a.php, mail/mail_send_hyoka_b.php, mail/mail_2tmp.php, mail/mail_1tmp.php, mail/mail_3tmp.php, mail/mail_4tmp.php

# concrete5 Cache Settings
Block Cache - Off
Overrides Cache - On
Full Page Caching - Off
Full Page Cache Lifetime - Every 6 hours (default setting).

# Server Software
Apache

# Server API
apache2handler

# PHP Version
7.3.15

# PHP Extensions
apache2handler, bcmath, bz2, calendar, Core, ctype, curl, date, dba, dom, enchant, exif, fileinfo, filter, ftp, gd, gettext, gmp, hash, iconv, imap, intl, json, ldap, libxml, mbstring, mcrypt, mysqli, mysqlnd, odbc, openssl, pcre, PDO, pdo_mysql, PDO_ODBC, pdo_pgsql, pdo_sqlite, pgsql, Phar, posix, pspell, recode, Reflection, session, shmop, SimpleXML, snmp, soap, sockets, SPL, sqlite3, standard, sysvmsg, sysvsem, sysvshm, tidy, tokenizer, wddx, xml, xmlreader, xmlrpc, xmlwriter, xsl, Zend OPcache, zip, zlib

# PHP Settings
max_execution_time - 3600
log_errors_max_len - 4096
max_file_uploads - 100
max_input_nesting_level - 64
max_input_time - 60
max_input_vars - 1000
memory_limit - 256M
post_max_size - 384M
upload_max_filesize - 256M
ldap.max_links - Unlimited
mbstring.regex_stack_limit - 100000
mysqli.max_links - Unlimited
mysqli.max_persistent - Unlimited
odbc.max_links - Unlimited
odbc.max_persistent - Unlimited
pcre.backtrack_limit - 1000000
pcre.recursion_limit - 100000
pgsql.max_links - Unlimited
pgsql.max_persistent - Unlimited
session.cache_limiter - no value
session.gc_maxlifetime - 7200
soap.wsdl_cache_limit - 5
opcache.max_accelerated_files - 4000
opcache.max_file_size - 0
opcache.max_wasted_percentage - 5

タグ:

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年1月30日 at 0:20
2021/1/29に配信した「第378回 週刊 concrete5」で取り上げました。
http://www.youtube.com/watch?v=svT42Rfvc3g
01:14:08あたりを参照してみてください。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年1月30日 at 8:11
aniyaさま

おはようございます。
いつも大変お世話になり、ありがとうございます。
情報のご共有、まことにありがとうございます。
早速拝見させていただきます。
coreのCSV出力周りのコードを参照するという
観点に気づいておりませんでした。
aniyaさま、いつもありがとうございます。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月1日 at 17:33
aniyaさま

いつもお世話になっております。
先日の週間concrete5 配信内容を参考に、取り急ぎ、Expressエンティティ
の属性名を取得して、リストからそれぞれの入力データをgetUserid();などの
メソッドで取得し、エントリーデータをループすることでcsvファイルとして
出力することはできました。
logs.php での csvファイル作成方法が大変役立ちました。
ありがとうございました。

引き続き、エンティティ名別にエントリーデータを動的に取得する方法
を試行中でございます。
完成いたしましたら、ご報告させていただきます
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月2日 at 12:41
取り急ぎ・・・
ざっくりアドバイスですいませんが、

> 引き続き、エンティティ名別にエントリーデータを動的に取得する方法
を試行中でございます。

コードを奥深くまで読み解く必要があるのですが、
Express の管理画面の方のコードを参考にされると良いと思います。

詳しくは金曜日に・・・
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月2日 at 14:13
katzさま

 いつもご支援ありがとうございます。
どうぞよろしくお願いいたします。
次回の週刊concrete5を楽しみにお待ち
しております。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月9日 at 17:35
katzさん
 いつも大変お世話になっております。
先週の週刊concrete5を拝聴させていただき、大変勉強になりました。
ありがとうございます。

番組内でご説明いただいた、エンティティのIDを取得しようと試みて
おります。

hissyさんよりご説明いただいた、
public function csv_export($treeNodeParentID = null){
$me = $this;
$parent = $me->getParentNode($treeNodeParentID);
$entity = $me->getEntity($parent);
...
}

において、$treeNodeParentID が、MYSQLの「ExpressEntities」テーブル
における "id" に該当すると思うのですが、違いますでしょうか?

hissyさんがご説明下さっているのは、ダッシュボードのExpressエンティティ
詳細画面でエントリーデータ一覧を表示させているため、
$me->getParentNodeID() で表示しているExpressエンティティのエントリー
データの親ID(エンティティID)を取得していると思うのですが、これを
エントリーリストから取得するとしますと、
まず、$entity = Express::getObjectByHandle('●●●●');
●●●●はエンティティのハンドル名
でエンティティ情報を取得してきて、そのデータのIDを
$id = $entity->getID();
で取得すればよいように考えたのですが、この考えは間違っておりますで
しょうか?

ExpressEntitiesテーブルの「id」が取得できれば、あとは、
public function csv_export と同じ方法でcsvファイルの作成ができると
考えております。
どうぞよろしくお願い申し上げます。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月9日 at 17:51
その辺は不要です。お送りしたコードのハイライト部分にもあえて含めてません。
$entity までは取れているようでしたので、そのあと必要な部分だけをハイライトでお送りしました。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月9日 at 18:02
hissyさん

ありがとうございます。
そこまでご配慮いただき、感謝申し上げます。
はい、上のようにして$entityを取得しておりますので、
これを public function csv_export に引き継いで、
一度試させていただきます。

ありがとうございます。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月12日 at 16:14
いつもお世話になっております。
viewのリストボックスで取得したエンティティ名(ハンドル名)を
controller側へ渡して$entname に代入し、エントリーデータを取得しようと
いたしました。
ところが、下記コードを実行しましても、CSVダウンロードのための
ダイアログボックス自体も表示されません。
なんの反応もない状態でございます。
コードの解釈が間違えていると思います。
$input['csvent'] に、viewで選択したエンティティ名'enqa'を渡しているのですが、
これが原因でしょうか?
ご教示いただければ幸いです。


public function action_submit(){
//CSV作成対象エンティティの取得
$input['csvent'] = $this->post('csvent');

if (isset($input['csvent']) && $input['csvent'] != ''){
$entname = $input['csvent'];
}


$entity = Express::getObjectByHandle($entname);
$headers = [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename=' . $entity->getHandle() . '.csv',
];
$config = $this->app->make('config');
$bom = $config->get('concrete.export.csv.include_bom') ? $config->get('concrete.charset_bom') : '';
$datetime_format = $config->get('concrete.export.csv.datetime_format');

return StreamedResponse::create(function () use ($entity, $me, $bom, $datetime_format) {
$entryList = new EntryList($entity);

$writer = $this->app->make(CsvWriter::class, [
$this->app->make(WriterFactory::class)->createFromPath('php://output', 'w'),
new Date()
]);
echo $bom;
$writer->insertHeaders($entity);
$writer->insertEntryList($entryList,$datetime_format);
}, 200, $headers);
}
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月16日 at 7:40
通常のコントローラーは、Responseオブジェクトを返すだけでいい感じに処理してくれるのですが、外部フォームはそうではないようです。

return StreamedResponse::create(function () use ($entity, $me, $bom, $datetime_format) {
...
}



$response = StreamedResponse::create(function () use ($entity, $me, $bom, $datetime_format) {
...
}
$response->send();

と変更すれば動きそうです
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月16日 at 10:35
hissyさん

 おはようございます。ありがとうございます。
2/12の週刊concrete5において、katzさんより、
viewから渡したエンティティハンドル名がどのように
なっているかなど、var_dump で確認してみてくださいと
教えていただきましたので、それぞれの変数を確認して
見ました。

var_dump($entname);
exit();
としたところ、$entname は、予定通り、エンティティのハンドル
名が渡っておりました。
その後、return StreamedRespons::create~
の上の行までは、正常に値が取れておりました。
return StreamedRespons::create~で何も取得できていない状態
になっておりましたので、教えていただいた方法で検証させて
いただきます。ありがとうございます。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月16日 at 13:21
ご教示ありがとうございます。
参照クラスを以下のように設定し、コードを変更いたしました。
そうしますと、「このサイトにアクセスできません。
ウェブページは一時的に停止しているか、新しいウェブアドレスに移動した可能性があります。」と表示されました(添付ファイル)。
参照クラス設定か、どこかで間違えている可能性もあるかと存じます。
どこが原因か、お教えいただけますと幸いでございます。どうぞよろしくお願い
申し上げます。

参照クラス・名前空間
namespace Application\Block\ExternalForm\Form\Controller;
use Concrete\Core\Controller\AbstractController;
use Concrete\Core\Csv\WriterFactory;
use Concrete\Core\Express\Export\EntryList\CsvWriter;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Concrete\Core\Entity\Express\Entity;
use Concrete\Core\Express\EntryList;
use Core;
use UserInfo;
use User;
use Express;

public function action_submit(){
//CSV作成対象エンティティの取得
$input['csvent'] = $this->post('csvent');
$me = $this;

if (isset($input['csvent']) && $input['csvent'] != ''){
$entname = $input['csvent'];
}

//$fileName = $entname.' download file';
$entity = Express::getObjectByHandle($entname);

$headers = [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename=' . $entity->getHandle() . '.csv',
];

$config = $this->app->make('config');
$bom = $config->get('concrete.export.csv.include_bom') ? $config->get('concrete.charset_bom') : '';
$datetime_format = $config->get('concrete.export.csv.datetime_format');
//ここまでのすべての変数は、中身が正常に取れておりました
$response = StreamedResponse::create(function () use ($entity, $me, $bom, $datetime_format) {
$entryList = new EntryList($entity);
$writer = $this->app->make(CsvWriter::class, [
$this->app->make(WriterFactory::class)->createFromPath('php://output', 'w'),
new Date()
]);
echo $bom;
$writer->insertHeaders($entity);
$writer->insertEntryList($entryList,$datetime_format);
}, 200, $headers);

$response->send();

$this->set('message', 'csvダウンロードが終了しました。');
}
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月17日 at 10:58
hissyさん

おはようございます。ありがとうございます!!できました!!
昨日投稿した「ページが表示できません」メッセージについては、
参照するクラスが抜けていたことが原因のようでございます。
ご迷惑をおかけいたしました(;^_^A

hissyさんのお教え通りに、$response = StreamRsponse::create(function () use...)
と致しまして、
$response->send(); を実行することで、ダイアログが表示され、無事ダッシュボード
と同じ機能が実現できました。
気になったところと致しましては、この方法でダウンロードしたcsvファイルを
ExcelからUTF-8で読み込んでみますと、
HTMLタグが一緒に吐き出されておりました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" type="text/css" href="/tkp_system/concrete/themes/elemental/css/bootstrap-modified.css">
<link href="/tkp_system/application/files/cache/css/elemental/main.css?ts=1599545416" rel="stylesheet" type="text/css" media="all">・・・

そこで、
$response->send();
の後にdie関数をかませることで、防止することができました。

$response->send();
die();

これで何とか解決できました。
hissyさん、katzさん、aniyaさん、フォーラムの皆さん、本当に
ありがとうございました。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月17日 at 11:05
die(); で強制するより \Core::shutdown(); の方が望ましいです。
適切に処理を終了してくれます。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月17日 at 11:10
hissyさん

 ご教示ありがとうございます。
さっそく、そのように実装させていただきます。
ありがとうございました!!
 

Re: Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月17日 at 11:35
hissyさん

 ありがとうございました。
無事、できました。

$response->send();
\Core::shutdown();
//die();
とすることで、HTMLタグもなく、CSVファイルが無事
ダウンロードできました。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月1日 at 15:59
katzさん、aniyaさん始め、フォーラムの皆さまには
いつもご支援いただき、感謝申し上げます。

週間concrete5 での配信内容を参考に、まず
logs.phpの public function csv を確認いたしました。

ここでのcsvファイル作成方法については、ほぼ予想通り、
CSVファイルオープン後、データのヘッダ行を$rows[]に
挿入、その後、各データ行を1行ずつ $rows[] に追加していく
ものでした。

そこでお聞きしたいことが、いま、エンティティが3つある
としまして、外部フォームのセレクトボックス(A、B、C)
を選択し、エンティティ名Aが選択された場合、エンティティ
Aのヘッダ行およびデータ行を取得します。

このとき、エンティティAの属性(例えば5つあるとして)名の
取得と、
エンティティのlistを取得した場合、
$results = $list->getResults();
で取得したリストから、それぞれの属性で入力された値の取得

if (count($results)){
foreach ($results as $rowdata){
$zokusei1 = $rowdata->getUserid();
$zokusei2 = $rowdata->getUsername();
...
}
}

 のgetUserid(); などを動的に定義したいと思いますが、この
方法が思い至っておりません。
Expressエントリーをそもそも、リストで取得していることが
間違えているような気がいたします。
お分かりの方がいらっしゃいましたら、ぜひお教えください。
どうぞよろしくお願い申し上げます。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月3日 at 14:41
小出しですいませんが、

concrete5 には CSV のインポート・エクスポートを行うライブラリ League/CSV ライブラリが同梱していて、こっちを使うとよりスマートに、CSV の出力を行うことができます。

全然、説明が無いのですが、
CSV でユーザーのインポート・エクスポートができるアドオンがあるので、
これを参考にエクスポートの部分を調整してもらえればと思います。

http://github.com/concrete5cojp/addon_csv_user_import_export
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月3日 at 16:45
おっと…csv_user_import_exportの作者です。このアドオンはほとんど参考にならないかと。

管理画面からのエクスポートと同じ機能ですよね?
このコードをコピペすればそのまま同じ機能です。

http://github.com/concrete5/concrete5/blob/8.5.4/concrete/src/Page/Controller/DashboardExpressEntriesPageController.php#L99-L117
 

Re: Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月4日 at 11:15
hissyさん

 おはようございます。
ありがとうございます。
ぜひ確認させていただきます。
追加する機能が増えるにつれ、まだまだ勉強不足を痛感
しております。
勉強させていただきます。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月4日 at 11:14
katzさん

 おはようございます。
ありがとうございます。まだまだ、研究が足りません(;^_^A
勉強させていただきます。
今週の週間concrete5も楽しみにいたしております。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月7日 at 16:49
2月5日に配信した「第379回 週刊 concrete5」で取り上げました。
http://www.youtube.com/watch?v=aDoR-AOtKAQ
29:25あたりを参照してみてください。

基本的にはhishikawaさんのアドバイスを参照してください、というまとめですが、
コードに関する具体的な補足説明を行っています。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月8日 at 9:44
動画でCSVWriterがライブラリであると解説されていますが、間違いです。
このクラスはconcrete5のコア機能で、エクスプレスエントリーをエクスポートするためにあらかじめ作られています。

逆に、私のアドオンが参考にならないのは、私のアドオンが使っているCsvWriterが外部ライブラリで、しかもconcrete5には同梱されていないものだからです。

以上、誤解を招いてはいけないと思い、補足しておきます。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月9日 at 9:17
hissyさん
 おはようございます。
ありがとうございます。よく理解できました。
このコアクラスと、ExpressエンティティIDを
動的に取得できれば、csvファイルダウンロード
機能が実装できると思います。
ありがとうございました。
 

Re: エクスプレスエントリーデータダウンロードを外部フォームから実行したい

2021年2月8日 at 10:58
aniyaさま、おはようございます。
いつもご支援を賜りまして、ありがとうございます。
今回の週間concrete5を拝聴し、hissyさんからご教示いただいた、Githubのコードを
確認させていただき、ExpressのCSVエクスポートの動きが理解できてまいりました。
external formのリストボックスで選択したExpressエンティティ(番号)を引数として
csvライブラリに渡して検証してみたいとおもいます。
concrete5には、フォームヘルパーやメールヘルパーと同様に、CsvWriterのような強力
なライブラリが最初から備わっているのは、本当に助かります。
1からphpコードを書くことに比べ、開発効率が格段に上がります。
ありがとうございます。頑張って解決いたします。