PHP でのデータストリーミングガイド
岩佐 孝浩
3 min read
PHP
この記事は、公開後3年以上が経過しています。
はじめに
URL Copied!
PHP でのデータストリーミング は、特に大規模なデータセットを扱う際に非常に有用なテクニックです。php://output
を使用することで、メモリの制約を回避しながら直接出力バッファに書き込むことができます。
データをストリームする理由
URL Copied!
データをストリームすることで効率的なメモリ使用が可能となり、特に大きな CSV、JSON、XML ファイルを扱う際に有効です。
例: PHP で CSV データをストリームする
URL Copied!
以下は、ダウンロード可能な CSV ファイルを作成する例です。この機能の中心は fopen('php://output', 'w');
を使用してストリームを開くことです。
App\Lib\Stream\DownloadStream.php
URL Copied!
<?php
namespace App\Lib\Stream;
/**
* Class DownloadStream
* ダウンロード可能なコンテンツをストリームするユーティリティを提供します。
*
* @package App\Lib\Stream
*/
class DownloadStream
{
public static function getStream(string $fileName)
{
// ファイルダウンロード用ヘッダを送信
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename={$fileName}");
// 出力ストリームを開く
$stream = fopen('php://output', 'w');
// フィルタを適用
stream_filter_prepend($stream, 'convert.iconv.utf-8/cp932'); // ShiftJIS に変換
stream_filter_register('CrlfFilter', 'App\Lib\Stream\Filter\CrlfFilter');
stream_filter_append($stream, 'CrlfFilter'); // 改行コードを CRLF に変換
return $stream;
}
}
改行コード用のカスタムストリームフィルタを作成
URL Copied!
Windows ユーザーにとって、改行コードを CRLF に変換することはしばしば必要です。以下はカスタムフィルタを作成する方法です。
App\Lib\Stream\Filter\CrlfFilter.php
<?php
namespace App\Lib\Stream\Filter;
/**
* Class CrlfFilter
* 改行コードを CRLF 形式に変換します。
*
* @package App\Lib\Stream\Filter
*/
class CrlfFilter extends \php_user_filter
{
public function filter($in, $out, &$consumed, $closing)
{
while ($bucket = stream_bucket_make_writeable($in)) {
// 改行コードを正規化
$bucket->data = preg_replace("/\r$/", "", $bucket->data);
$bucket->data = preg_replace("/\n$/", "", $bucket->data);
// CRLF を追加
$bucket->data .= "\r\n";
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
使用例
URL Copied!
以下のコードは、DownloadStream
ユーティリティを使用して CSV ファイルを作成し、ダウンロードする方法を示しています。
// ファイル名を定義
$fileName = 'example.csv';
// ダウンロードストリームを取得
$stream = DownloadStream::getStream($fileName);
// CSV ヘッダーを書き込む
fputcsv($stream, [
'last_name',
'first_name',
'company',
]);
// CSV レコードを書き込む
fputcsv($stream, [
'Jane',
'Doe',
'ABC Company',
]);
// ストリームを閉じる
fclose($stream);
まとめ
URL Copied!
php://output を使用したデータストリーミングは、大規模なファイルをメモリに負荷をかけずに扱う効率的な方法です。このアプローチは、特に大規模データセットを CSV にエクスポートする場合に適しています。さらに、カスタムフィルタを追加することで、エンコーディングや改行コード変換など、ストリームを特定の要件に合わせて柔軟に調整できます。
Happy Coding! 🚀