fw3/streams

Flywheel3 框架:流式库

1.3.0 2023-11-24 04:46 UTC

This package is auto-updated.

Last update: 2024-08-30 01:26:14 UTC


README

快速开发框架Flywheel3的流式处理库。

支持的PHP版本是7.2.0及以上。

对于旧版本PHP 5.3.3及以上环境,请使用fw3-for-old/streams

如果您想要轻松简单地使用,请参考导入方法,导入库后,尝试应用:初始化设置也交给库处理中的实现。

导入方法

使用composer require fw3/streams进行安装。

Packagist

主要功能

流式过滤器

编码转换流式过滤器:ConvertEncodingFilter

在文件输入输出时执行编码转换的过滤器。

利用内置的局部更改处理和替代字符设置处理,可以确保获得预期的一致输出。

此外,通过使用附带的Spec类群,可以直观、简单、安全地进行设置。此外,在ZIP扩展应用环境中,还可以透明地处理ZIP文件内的CSV文件。

<?php

use fw3\streams\filters\ConvertEncodingFilter;
use fw3\streams\filters\utilitys\StreamFilterSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertEncodingSpec;

// 必須:実行時のロカールと代替文字設定を先行して設定します
ConvertEncodingFilter::startChangeLocale();

// お好みで:変換不能文字があった場合の代替文字設定
ConvertEncodingFilter::startChangeSubstituteCharacter();

// `convert.encoding.*`としてフィルタ登録
StreamFilterSpec::registerConvertEncodingFilter();

//==============================================
// 書き込み
//==============================================
// フィルタの設定:`php://filter/write=convert.encoding.SJIS-win:UTF-8/resource=path to csv file`として構築
$spec   = StreamFilterSpec::resource($path_to_csv_file)->write([
    StreamFilterConvertEncodingSpec::toSjisWin()->fromUtf8(),
]);

// CP932としてCSV書き込みを行う(\SplFileObjectでも使用できます。)
$fp     = \fopen($spec->build(), 'wb');
foreach ($rows as $row) {
    \fputcsv($fp, $row);
}
\fclose($fp);

//==============================================
// 読み込み
//==============================================
// フィルタの設定:`php://filter/read=convert.encoding.UTF-8:SJIS-win/resource=path to csv file`として構築
$spec   = StreamFilterSpec::resource($path_to_csv_file)->read([
    StreamFilterConvertEncodingSpec::fromUtf8()->toSjisWin(),
]);

// UTF-8としてCSV読み込みを行う(\SplFileObjectでも使用できます。)
$rows   = [];
$fp     = \fopen($spec->build(), 'rb');
for (;($row = \fgetcsv($fp, 1024)) !== FALSE;$rows[] = $row);
\fclose($fp);

// ロカールと代替文字設定を元に戻します
ConvertEncodingFilter::endChangeSubstituteCharacter();
ConvertEncodingFilter::endChangeLocale();

行尾换行符转换流式过滤器:ConvertLinefeedFilter

在文件输入输出时执行行尾换行符转换的过滤器。

无论系统或系统设置如何,都可以通过fgetcsv等处理,在行尾添加期望的换行符。

<?php

use fw3\streams\filters\utilitys\StreamFilterSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertLinefeedSpec;

// `convert.linefeed.*`としてフィルタ登録
StreamFilterSpec::registerConvertLinefeedFilter();

//==============================================
// 書き込み
//==============================================
// フィルタの設定:`php://filter/write=convert.linefeed.CRLF:ALL/resource=path to csv file`として構築
$spec   = StreamFilterSpec::resource($path_to_csv_file)->write([
    StreamFilterConvertLinefeedSpec::toCrLf()->fromAll(),
]);

// 行末の改行コードをCRLFとしてCSV書き込みを行う(\SplFileObjectでも使用できます。)
$fp     = \fopen($spec->build(), 'wb');
foreach ($rows as $row) {
    \fputcsv($fp, $row);
}
\fclose($fp);

应用:安全的CSV输入输出

如下所示,可以安全地执行可由Excel安全读取的CSV文件的输入输出。

<?php

use fw3\streams\filters\ConvertEncodingFilter;
use fw3\streams\filters\utilitys\StreamFilterSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertEncodingSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertLinefeedSpec;

//==============================================
// 設定
//==============================================
$path_to_csv    = '';   // CSVファイルのパスを設定して下さい

//----------------------------------------------
// 必須:実行時のロカールと代替文字設定を先行して設定します
//----------------------------------------------
// Windowsや一部Unix系OS環境下ではシステムデフォルトのロカールを使用すると、fgetcsv関数が期待した通りに動作しなくなります
// 引数なしでConvertEncodingFilter::startChangeLocale();を実行した場合、OSやPHPのバージョンを加味した上で無難なロカール設定を行います
// 引数を与える事で任意のロカールに設定する事も出来ます
// 設定前のロカールはスタックされるため、「ConvertEncodingFilter::endChangeLocale();」で元に戻すことができます。
//----------------------------------------------
ConvertEncodingFilter::startChangeLocale();

//----------------------------------------------
// お好みで:変換不能文字があった場合の代替文字設定
//----------------------------------------------
// これは「艗」などのエンコーディング変換ができない文字を代替する文字の設定です
// デフォルトではエンティティ(&#x8257;)に変換されます
// 引数を与える事で固定の代替文字やユニコード(U+8257)、または消去するなどの挙動の変更が可能です
// 設定前の代替文字はスタックされるため、「ConvertEncodingFilter::endChangeSubstituteCharacter();」で元に戻すことができます
//----------------------------------------------
ConvertEncodingFilter::startChangeSubstituteCharacter();

//----------------------------------------------
// フィルタ登録
//----------------------------------------------
// 引数を使用することでお好きなフィルタ名を設定することができます。
//
// StreamFilterSpec::registerConvertEncodingFilter(StreamFilterConvertEncodingSpec::DEFAULT_FILTER_NAME);
// StreamFilterSpec::registerConvertLinefeedFilter(StreamFilterConvertLinefeedSpec::DEFAULT_FILTER_NAME);
//----------------------------------------------
StreamFilterSpec::registerConvertEncodingFilter();
StreamFilterSpec::registerConvertLinefeedFilter();

//==============================================
// 書き込み
//==============================================
// フィルタの設定
$spec   = StreamFilterSpec::resource($path_to_csv)->write([
    StreamFilterConvertEncodingSpec::toSjisWin()->fromUtf8(),
    StreamFilterConvertLinefeedSpec::toCrLf()->fromAll(),
]);

// CP932、行末の改行コードCRLFとしてCSV書き込みを行う(\SplFileObjectでも使用できます。)
$fp     = \fopen($spec->build(), 'wb');
foreach ($rows as $row) {
    \fputcsv($fp, $row);
}
\fclose($fp);

//==============================================
// 読み込み
//==============================================
// フィルタの設定
$spec   = StreamFilterSpec::resource($path_to_csv)->read([
    StreamFilterConvertEncodingSpec::toUtf8()->fromSjisWin(),
]);

// UTF-8としてCSV読み込みを行う(\SplFileObjectでも使用できます。)
$rows   = [];
$fp     = \fopen($spec->build(), 'rb');
for (;($row = \fgetcsv($fp, 1024)) !== FALSE;$rows[] = $row);
\fclose($fp);

//==============================================
// ロカールと代替文字設定を元に戻します
//==============================================
ConvertEncodingFilter::endChangeSubstituteCharacter();
ConvertEncodingFilter::endChangeLocale();

应用:通过HTTP下载CSV

如下所示,可以轻松实现可由Excel安全读取的CSV文件的下载。

<?php

use fw3\streams\filters\ConvertEncodingFilter;
use fw3\streams\filters\utilitys\StreamFilterSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertEncodingSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertLinefeedSpec;

//==============================================
// 設定
//==============================================
// 必須:実行時のロカールと代替文字設定を先行して設定します
ConvertEncodingFilter::startChangeLocale();

// お好みで:変換不能文字があった場合の代替文字設定
ConvertEncodingFilter::startChangeSubstituteCharacter();

// フィルタ登録
StreamFilterSpec::registerConvertEncodingFilter();
StreamFilterSpec::registerConvertLinefeedFilter();

//==============================================
// 例:PDOで取得したデータをそのままCSVとしてDLさせてみる
//==============================================
// フィルタの設定
$spec   = StreamFilterSpec::resourceOutput()->write([
    StreamFilterConvertEncodingSpec::toSjisWin()->fromUtf8(),
    StreamFilterConvertLinefeedSpec::toCrLf()->fromAll(),
]);

// 仮のDB処理:実際のDB処理に置き換えてください
$pdo    = new \PDO('spec to dsn');
$pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
$stmt   = $pdo->prepare('SELECT * FROM table');
$stmt->execute();

// 仮のHTTP Response Header
\header('Content-Type: application/octet-stream');
\header('Content-Disposition: attachment; filename=fw3-sample.csv');

// CP932、行末の改行コードCRLFとしてCSV書き込みを行う(\SplFileObjectでも使用できます。)
$fp     = \fopen($spec->build(), 'wb');
foreach ($stmt as $row) {
    \fputcsv($fp, $row);
}
\fclose($fp);

//==============================================
// ロカールと代替文字設定を元に戻します
//==============================================
ConvertEncodingFilter::endChangeSubstituteCharacter();
ConvertEncodingFilter::endChangeLocale();

应用:初始化设置也交给库处理

可以将过滤器注册、局部和替代字符的设置以及执行后的恢复等易变成板的处理交给库执行。

安全的CSV输入输出
<?php

use fw3\streams\filters\utilitys\StreamFilterSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertEncodingSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertLinefeedSpec;

//==============================================
// 設定
//==============================================
$rows   = [[]]; // データ

$path_to_csv    = '';   // CSVファイルのパスを設定して下さい

//----------------------------------------------
// 一括即時実行
//----------------------------------------------
// フィルタ登録、ロカールと代替文字の設定と実行後のリストアも包括して実行します。
// コールバックの実行中に例外が発生してもロカールと代替文字のリストアは実行されます。
//----------------------------------------------
$result = StreamFilterSpec::decorateForCsv(function () use ($path_to_csv, $rows) {
    //==============================================
    // 書き込み
    //==============================================
    // フィルタの設定
    $spec   = StreamFilterSpec::resource($path_to_csv)->write([
        StreamFilterConvertEncodingSpec::toSjisWin()->fromUtf8(),
        StreamFilterConvertLinefeedSpec::toCrLf()->fromAll(),
    ]);

    // CP932、行末の改行コードCRLFとしてCSV書き込みを行う(\SplFileObjectでも使用できます。)
    $fp     = \fopen($spec->build(), 'r+b');
    foreach ($rows as $row) {
        \fputcsv($fp, $row);
    }
    \fclose($fp);

    //==============================================
    // 読み込み
    //==============================================
    // フィルタの設定
    $spec   = StreamFilterSpec::resource($path_to_csv)->read([
        StreamFilterConvertEncodingSpec::toUtf8()->fromSjisWin(),
    ]);

    // UTF-8としてCSV読み込みを行う(\SplFileObjectでも使用できます。)
    $rows   = [];
    $fp     = \fopen($spec->build(), 'r+b');
    for (;($row = \fgetcsv($fp, 1024)) !== FALSE;$rows[] = $row);
    \fclose($fp);

    return $rows;
});
安全的CSV输入输出:\SplFileObject示例
<?php

use fw3\streams\filters\utilitys\StreamFilterSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertEncodingSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertLinefeedSpec;

//==============================================
// 設定
//==============================================
$rows   = [[]]; // データ

$path_to_csv    = '';   // CSVファイルのパスを設定して下さい

//----------------------------------------------
// 一括即時実行
//----------------------------------------------
// フィルタ登録、ロカールと代替文字の設定と実行後のリストアも包括して実行します。
// コールバックの実行中に例外が発生してもロカールと代替文字のリストアは実行されます。
//----------------------------------------------
$result = StreamFilterSpec::decorateForCsv(function () use ($path_to_csv, $rows) {
    //==============================================
    // 書き込み
    //==============================================
    // フィルタの設定
    $spec   = StreamFilterSpec::resource($path_to_csv)->write([
        StreamFilterConvertEncodingSpec::toSjisWin()->fromUtf8(),
        StreamFilterConvertLinefeedSpec::toCrLf()->fromAll(),
    ]);

    // CP932、行末の改行コードCRLFとしてCSV書き込みを行う
    $csvFile    = new \SplFileObject($spec->build(), 'r+b');
    foreach ($csvFile as $row) {
        $file->fputcsv($row);
    }

    //==============================================
    // 読み込み
    //==============================================
    // フィルタの設定
    $spec   = StreamFilterSpec::resource($path_to_csv)->read([
        StreamFilterConvertEncodingSpec::toUtf8()->fromSjisWin(),
    ]);

    // UTF-8としてCSV読み込みを行う(\SplFileObjectでも使用できます。)
    $rows       = [];
    $csvFile    = new \SplFileObject($spec->build(), 'r+b');
    $csvFile->setFlags(\SplFileObject::READ_CSV);
    foreach ($csvFile as $row) {
        $rows[] = $row;
    }

    return $rows;
});
处理ZIP文件内的CSV文件的示例
<?php

use fw3\streams\filters\utilitys\StreamFilterSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertEncodingSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertLinefeedSpec;

//==============================================
// 設定
//==============================================
$path_to_csv    = '';   // CSVファイルを含むZIPファイルのパスを設定して下さい

//----------------------------------------------
// 一括即時実行
//----------------------------------------------
// フィルタ登録、ロカールと代替文字の設定と実行後のリストアも包括して実行します。
// コールバックの実行中に例外が発生してもロカールと代替文字のリストアは実行されます。
//----------------------------------------------
$result = StreamFilterSpec::decorateForCsv(function () use ($path_to_csv) {
    //==============================================
    // 読み込み
    //==============================================
    // フィルタの設定:`$path_to_csv`が示すZIPファイル内の`temp/test.csv`にアクセスする例
    $spec   = StreamFilterSpec::resourceZip($path_to_csv, 'temp/test.csv')->read([
        StreamFilterConvertEncodingSpec::toUtf8()->fromSjisWin(),
    ]);

    // UTF-8としてCSV読み込みを行う(\fopenでも使用できます。)
    $rows       = [];
    $csvFile    = new \SplFileObject($spec->build(), 'r+b');
    $csvFile->setFlags(\SplFileObject::READ_CSV);

    // ZIPストリームの場合、rewind出来ないためforeachを使用できません。
    // そのため、次の例ではforを利用しています。
    for (;\is_array($row = $csvFile->fgetcsv());) {
        $rows[] = $row;
    }

    return $rows;
});
通过HTTP下载CSV
<?php

use fw3\streams\filters\utilitys\StreamFilterSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertEncodingSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertLinefeedSpec;

//----------------------------------------------
// 一括即時実行
//----------------------------------------------
// フィルタ登録、ロカールと代替文字の設定と実行後のリストアも包括して実行します。
// コールバックの実行中に例外が発生してもロカールと代替文字のリストアは実行されます。
//----------------------------------------------
StreamFilterSpec::decorateForCsv(function () {
    //==============================================
    // 例:PDOで取得したデータをそのままCSVとしてDLさせてみる
    //==============================================
    // フィルタの設定
    $spec   = StreamFilterSpec::resourceOutput()->write([
        StreamFilterConvertEncodingSpec::toSjisWin()->fromUtf8(),
        StreamFilterConvertLinefeedSpec::toCrLf()->fromAll(),
    ]);

    // 仮のDB処理:実際のDB処理に置き換えてください
    $pdo    = new \PDO('spec to dsn');
    $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
    $stmt   = $pdo->prepare('SELECT * FROM table');
    $stmt->execute();

    // 仮のHTTP Response Header
    \header('Content-Type: application/octet-stream');
    \header('Content-Disposition: attachment; filename=fw3-sample.csv');

    // CP932、行末の改行コードCRLFとしてCSV書き込みを行う(\SplFileObjectでも使用できます。)
    $fp     = \fopen($spec->build(), 'wb');
    foreach ($stmt as $row) {
        \fputcsv($fp, $row);
    }
    \fclose($fp);
});