概要
SplFileObject
によるCSVファイルの読み込みについて整理する。手順概略は以下のとおり。
- ファイル名を指定して
SplFileObject
のインスタンスを生成$file = new \SplFileObject('csvファイルパス');
$open_mode
はデフォルト値の'r'
(読み込み)
- CSV読み込みのためのフラグをセット
$file.setFlags(...);
- ファイルを読み込み
foreach
で行単位データを取得- 行データは各フィールド値を要素とする配列
なお、Splは”Standard PHP Library”の略。
基本例~一括読み込み
例として、GETリクエストに応じて所定の場所に配置されたCSVファイルを読みだし、行データを要素とする配列に格納し、その内容をブラウザーに表示するアプリケーションを考える。
CSVファイルの配置
storage/app/
ディレクトリーにCSVファイルを配置した場合は、storage_path()
関数にstorage
ディレクトリーを基準としたパスを指定してフルパスを得ることができる。
たとえば以下の内容のファイルをstorage/app/csv_sample_utf8.csv
として配置する(エンコーディングはUTF-8)。3つのカラムがカンマ','
で区切られている。
1 2 3 4 5 6 |
東北支店,宮城県仙台市,022-111-1111 関東支店,埼玉県大宮市,048-222-2222 中部支店,愛知県名古屋市,052-333-3333 近畿支店,大阪府大阪市,06-4444-4444 中国支店,広島県広島市,082-555-5555 九州支店,福岡県福岡市,092-666-6666 |
ルーティング
以下の様にルーティング設定する。
1 |
Route::get('/csv_sample', 'SampleController@csvSample'); |
コントローラー~処理本体
コード
コントローラーのアクションは以下のとおり。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public function csvSample() { $file = new \SplFileObject(storage_path('app/csv_sample_utf8.csv')); $file->setFlags( \SplFileObject::READ_CSV | \SplFileObject::READ_AHEAD | \SplFileObject::SKIP_EMPTY | \SplFileObject::DROP_NEW_LINE ); $lines = []; foreach($file as $line) { $lines[] = $line; } $file = null; $vars = [ 'title' => 'CSV読み込みサンプル', 'lines' => $lines, ]; return view('samples.csv_sample', $vars); } } |
SplFileObjectインスタンスの生成
PHPのSplFileObject
のインスタンスを、CSVファイルのパスを指定して生成する。
- LaravelでPHPのクラスを使う場合は、クラス名の冒頭に
'\'
を記述 storage_path()
関数によりアプリケーションのstorage
ディレクトリーを基準にしたCSVファイルのパスを指定
フラグの設定
SplFileObject
クラスのsetFlags()
メソッドで、必要なフラグを'|'
(or)で連ねて設定する。CSV読み込み時のフラグの影響についてはこちらを参照。
ファイルの読み込み
ファイルの各行をforeach
で取り出し、配列に格納していく。
1 2 3 4 |
$lines = []; foreach($file as $line) { $lines[] = $line; } |
各行はREAD_CSV
フラグによりCSVとみなされ、3つのフィールドが分解されて要素数3の配列になる。この結果、$lines
には6行分のCSVから読み込んだ配列が格納され、各配列は3つのフィールドに対応する要素を持つ。
ファイルクローズ
ファイルクローズのコマンドはないが、インスタンスの参照変数にnull
を代入してインスタンスを破棄している。
1 |
$file = null; |
PHPマニュアル(SplFileObject
)のUser Contributed Notes (64)でSplFileObject
のインスタンスにnull
をセットする意義が示されている。
ビューへの引継ぎ
タイトルとCSVから読み込んだ配列をビューに渡している。
ビューにおける表示
ビューでは、コントローラーから受け取った変数をHTMLとして展開している。
1 2 3 4 |
<h1>{{ $title }}</h1> @foreach($lines as $line) <p>{{ $line[0] }}, {{ $line[1] }}, {{ $line[2] }}</p> @endforeach |
以下はブラウザーでの表示例。
ファイルの順次読込
CSVファイルのサイズがかなり大きい可能性がある場合、一括して配列に読み込むとサーバーのメモリーを過大に圧迫することが考えられる。
CSVの内容をデータベースに登録するような処理の場合、1行ずつ読み込んで処理し、サーバーの負荷を軽減することを検討すべき。
エンコーディング
読み込むCSVファイルのエンコーディングがUTF-8以外の場合、そのまま読み込んだだけでは適正に扱えない。このようなことは表計算ソフトで作成したファイルがShift-JISというのはよくある。
SplFileObject
でCSVファイルを読み込む場合、1行のデータが各フィールドに対応した要素を持つ配列となるので、mb_covert_variables
を使う。
1 2 3 4 5 |
$lines = []; foreach($file as $line) { mb_convert_variables("UTF-8", "SJIS", $line); $lines[] = $line; } |