🐘
PHPでCSVを扱うならleague/csvが便利【基本的な使い方まとめ】
こんにちは、たつきちです。
エンジニア歴12年ぐらいで今はベンチャー企業のCTOをしています。
この記事では、PHPでCSVデータを扱うためのライブラリ league/csv
をご紹介します。
ぜひ最後までお付き合いください。
league/csvとは
league/csv は、PHPでCSVデータを簡単かつ柔軟に扱うためのライブラリです。
従来のように SplFileObject::fgetcsv とかを使って低レイヤーのコードを自力で書かなくても、いい感じでCSVデータを抽象化してくれます。
例えば以下のような簡潔なコードでCSVファイルを扱うことができます👍
CSVファイル
PHPコード
<?php
use League\Csv\Reader;
$csv = Reader::createFromPath('/path/to/your/csv/file.csv', 'r');
$csv->setHeaderOffset(0);
foreach ($csv as $row) {
var_dump($row);
}
// array (size=3)
// 'id' => string '1' (length=1)
// 'name' => string 'Tommy Yount' (length=11)
// 'email' => string 'tommy_yount@gmail.com' (length=21)
// array (size=3)
// 'id' => string '2' (length=1)
// 'name' => string 'Hye Panter' (length=10)
// 'email' => string 'hye_panter@gmail.com' (length=20)
// array (size=3)
// 'id' => string '3' (length=1)
// 'name' => string 'Keva Bandy' (length=10)
// 'email' => string 'keva_bandy@gmail.com' (length=20)
基本的な使い方
CSVファイルを読み込む
use League\Csv\Reader;
$csv = Reader::createFromPath('/path/to/your/csv/file.csv', 'r');
$csv->setHeaderOffset(0);
foreach ($csv as $row) {
var_dump($row);
}
CSVファイルを途中から読み込む
use League\Csv\Reader;
use League\Csv\Statement;
$csv = Reader::createFromPath('/path/to/your/csv/file.csv', 'r');
$csv->setHeaderOffset(0);
// 2行目(0始まり)から1行だけを読み込む
$stmt = (new Statement())
->offset(2)
->limit(1)
;
$rows = $stmt->process($csv);
foreach ($rows as $row) {
var_dump($row);
}
// array (size=3)
// 'id' => string '3' (length=1)
// 'name' => string 'Keva Bandy' (length=10)
// 'email' => string 'keva_bandy@gmail.com' (length=20)
SJIS-winのCSVファイルをUTF-8に変換して読み込む
use League\Csv\CharsetConverter;
use League\Csv\Reader;
$csv = Reader::createFromPath('/path/to/your/csv/file.csv', 'r');
$csv->setHeaderOffset(0);
// 文字コードを変換
CharsetConverter::addTo($csv, 'SJIS-win', 'UTF-8');
foreach ($csv as $row) {
var_dump($row);
}
タブ区切りのCSV(TSV)ファイルを読み込む
use League\Csv\Reader;
$csv = Reader::createFromPath('/path/to/your/csv/file.csv', 'r');
$csv->setHeaderOffset(0);
// デリミタをタブ文字に変更
$csv->setDelimiter("\t");
foreach ($csv as $row) {
var_dump($row);
}
注意点(僕が無駄にハマったところ)
上記の例でCSVデータを1行ずつ出力した際、
array (size=3)
'id' => string '1' (length=1)
'name' => string 'Tommy Yount' (length=11)
'email' => string 'tommy_yount@gmail.com' (length=21)
このように
[
'列名' => '値',
'列名' => '値',
'列名' => '値',
]
という形の配列として出力されていました。
しかし、例えば以下のように $csv->setHeaderOffset(0);
をせずに同じ処理を実行すると…
use League\Csv\Reader;
$csv = Reader::createFromPath('/path/to/your/csv/file.csv', 'r');
// $csv->setHeaderOffset(0);
foreach ($csv as $row) {
var_dump($row);
}
以下のように出力されます。
array (size=3)
0 => string 'id' (length=2)
1 => string 'name' (length=4)
2 => string 'email' (length=5)
array (size=3)
0 => string '1' (length=1)
1 => string 'Tommy Yount' (length=11)
2 => string 'tommy_yount@gmail.com' (length=21)
array (size=3)
0 => string '2' (length=1)
1 => string 'Hye Panter' (length=10)
2 => string 'hye_panter@gmail.com' (length=20)
array (size=3)
0 => string '3' (length=1)
1 => string 'Keva Bandy' (length=10)
2 => string 'keva_bandy@gmail.com' (length=20)
列名を添え字とする連想配列ではなく、CSVデータを物理的に配列化したものが出力されています。
$csv->setHeaderOffset(0);
が、 「CSVの何行目(0始まり)がヘッダー行なのか」を教える 処理なので、これを実行しないとヘッダーの内容が分からないのです。
僕は以前これを理解していなくて無駄にハマったので、皆さんはお気をつけください😅
まとめ
- PHPでCSVを扱うならleague/csvが便利
- 巨大CSVファイルを読み込むときもストリーム経由なのでメモリを大量消費しなくてありがたい
-
$csv->setHeaderOffset({ヘッダー行の位置});
を実行するのとしないのとでCSVデータの配列の形式が異なるので要注意
Discussion