topic: file-io (read / write / CSV / paths / upload概念) / ch04 — CSV を読み書きする / 演習 01
📝 ドリル 01 — CSV を読んで整形出力
問題
__DIR__ . '/tests/data/users.csv' を読み、各データ行を "id: name (age歳)" の形式で出力してください。
データファイル (tests/data/users.csv):
id,name,age
1,太郎,20
2,花子,25
3,次郎,30
期待される出力:
1: 太郎 (20歳)
2: 花子 (25歳)
3: 次郎 (30歳)
(1 行目のヘッダ id,name,age は出力に含めない)
採点
php scripts/grade.php topics/14-file-io/ch04-csv/drill/01-read-csv/
ヒント
$fp = fopen(__DIR__ . '/tests/data/users.csv', 'r');
$header = fgetcsv($fp, 0, ',', '"', ''); // 1 行目を読み捨てる
while (($row = fgetcsv($fp, 0, ',', '"', '')) !== false) {
[$id, $name, $age] = $row;
echo "{$id}: {$name} ({$age}歳)\n";
}
fclose($fp);fgetcsvは 1 行を配列で返す (数値添字)。[0]=id, [1]=name, [2]=age- ヘッダ行は ループに入る前に 1 回だけ読み捨てる
- 配列の分配代入
[$a, $b, $c] = $row;で列を変数に取り出せる (PHP 7.1+) - 第 2〜5 引数 (
length,separator,enclosure,escape) を明示 — PHP 8.4 以降 で警告が出るのを防ぐ
つまづいたら
- 出力の 1 行目が
"id: name (age歳)"になる → ヘッダ行を 読み捨てていない。ループに入る前にfgetcsv($fp)を 1 回呼ぶ ageが"20歳"ではなく"20.0歳"になる →(float)キャストやnumber_formatを使っている。fgetcsvの値は 文字列のまま で OK
テストケース
期待される出力
1: 太郎 (20歳)
2: 花子 (25歳)
3: 次郎 (30歳)
📄 starter.php(雛形)
このコードから書き始めてください。
<?php
// TODO: tests/data/users.csv のパスを __DIR__ ベースで組み立てる
// TODO: fopen でファイルを 'r' モードで開く
// TODO: 1 行目 (ヘッダ: id,name,age) を fgetcsv で読み捨てる
// PHP 8.4+ では 第 2〜5 引数を明示する: fgetcsv($fp, 0, ',', '"', '')
// TODO: while (($row = fgetcsv($fp, 0, ',', '"', '')) !== false) で行ごとに処理
// [$id, $name, $age] = $row;
// echo "{$id}: {$name} ({$age}歳)\n";
// TODO: fclose で閉じる
✅ 解答例を見る(自分で解いてから)
<?php
// users.csv (id,name,age) を読み、"id: name (age歳)" の形式で出力する
$path = __DIR__ . '/tests/data/users.csv';
$fp = fopen($path, 'r');
if ($fp === false) {
fwrite(STDERR, "open failed: $path\n");
exit(1);
}
// 1 行目 (ヘッダ) を読み捨てる
// PHP 8.4+ では fgetcsv の引数 (length, separator, enclosure, escape) を明示する
$header = fgetcsv($fp, 0, ',', '"', '');
// 2 行目以降をループ
while (($row = fgetcsv($fp, 0, ',', '"', '')) !== false) {
[$id, $name, $age] = $row;
echo "{$id}: {$name} ({$age}歳)\n";
}
fclose($fp);