From f81638a7b3ed486a2fbb65454580ee73163a443b Mon Sep 17 00:00:00 2001 From: a-kizaki Date: Thu, 22 Oct 2026 08:48:13 +0900 Subject: [PATCH] no message --- EmployeeData.csv | 4 + Readme.md | 102 +++++++++ database/abstracts/BaseAccess.php | 103 +++++++++ database/employees/EmployeeAccess.php | 174 ++++++++++++++++ database/interfaces/DataAccessInterface.php | 8 + public/controller.php | 127 ++++++++++++ public/employee_list.php | 72 +++++++ public/employee_register.php | 44 ++++ public/employee_update.php | 51 +++++ public/index.php | 30 +++ ヒント.md | 219 ++++++++++++++++++++ 仕様書/単体テスト仕様書.xlsx | Bin 0 -> 31667 bytes 仕様書/結合テスト仕様書.xlsx | Bin 0 -> 24724 bytes 13 files changed, 934 insertions(+) create mode 100644 EmployeeData.csv create mode 100644 Readme.md create mode 100644 database/abstracts/BaseAccess.php create mode 100644 database/employees/EmployeeAccess.php create mode 100644 database/interfaces/DataAccessInterface.php create mode 100644 public/controller.php create mode 100644 public/employee_list.php create mode 100644 public/employee_register.php create mode 100644 public/employee_update.php create mode 100644 public/index.php create mode 100644 ヒント.md create mode 100644 仕様書/単体テスト仕様書.xlsx create mode 100644 仕様書/結合テスト仕様書.xlsx diff --git a/EmployeeData.csv b/EmployeeData.csv new file mode 100644 index 0000000..3ecdf53 --- /dev/null +++ b/EmployeeData.csv @@ -0,0 +1,4 @@ +1610000001,"山田太郎",yamada@gmail.com +1610000002,"鈴木花子",suzuki@gmail.com +1610000003,"麻枝史明",maeda@gmail.com +1610000004,"丸田章介",maruda@gmail.com diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..5c163f3 --- /dev/null +++ b/Readme.md @@ -0,0 +1,102 @@ +# 社員メンテナンスシステム 演習課題 + +## はじめに(演習の⽬的と取り組み⽅) +当演習は、講義で学んだことを⾃⼒で実践できるようになるために実施します。 そのために以下の内容を守って演習に取り組んでください。 + +### 納品物、納期を守りましょう +この演習は、実際の仕事を想定した内容です。 +提出物の内容と提出期限は必ず守ってください。 +作業が間に合わない、提出物に問題が出そうな場合は、**必ずルールにしたがって適切な相⼿に相談してください**。 + +### 適切な⼿順で開発しましょう +プログラムを書き始める前に、**README.md** や**仕様書**(配布されている場合) を必ず読んでください。 +「**何を作るのか**」、「**どこまで作ればよいのか**」を理解してから作業を始めてください。 + +### 知らないことは⾃分で調べましょう +この演習には、**講義で扱っていない内容が⼀部含まれています**。 +その場合は、インターネットなどで⾃分で調べながら進めてください。 +調べることも、エンジニアにとって⼤切なスキルの⼀つです。 + + +## 演習目的 +**継承** +- 共通処理(CSVの読み書き)は、BaseAccess という抽象クラスにまとめています。 + +**インタフェース** +- DataAccessInterface によって、EmployeeAccess クラスは必ず getAll(), add(), update(), delete() を実装することが保証されます。 + +**カプセル化** +- バリデーションロジック(`validateEmployeeData()`)やデータ変換ロジック(`convertRowToEmployee()`)をprivateメソッドとして隠蔽し、外部から直接アクセスできないようにしています。 +- プロパティ(`$file`)はprotectedで定義し、継承クラスからのみアクセス可能にしています。 +- これにより、クラスの内部実装の詳細を隠し、外部からは公開されたメソッドのみを使用する設計になっています。 + +**例外処理** +- ファイル操作やデータ検証でエラーが発生した場合、適切な例外(`InvalidArgumentException`、`RuntimeException`)をスローします。 +- controller.phpでは、これらの例外をキャッチしてユーザーに分かりやすいエラーメッセージを表示します。 + +これにより、同じ処理を複数のクラスに記述せずに再利用できる設計のメリットと、 +将来的に DB 連携版や部署 CRUD への拡張が容易になる点を体感してもらいます。 + + +## フォルダ構成 +project/ +├─ database/ +│ ├─ abstracts/ +│ │ └─ BaseAccess.php // CSV共通処理の抽象クラス +│ ├─ interfaces/ +│ │ └─ DataAccessInterface.php // CRUD操作のインタフェース +│ |─ employees/ +│ | └─ EmployeeAccess.php // 社員のCSV操作を実装したクラス +├─ EmployeeData.csv // 社員情報のCSVファイル +│─ public/ +│ ├─ controller.php // 各画面からの指示を処理するファイル +│ ├─ employee_list.php // 社員一覧表示画面 +│ ├─ employee_register.php // 社員登録画面 +│ ├─ employee_update.php // 社員更新画面 +│ └─ index.php // ホーム画面(各機能へのリンクあり) + + +## 課題内容 +**database/employees/EmployeeAccess.php** の TODOコメントに従って、各メソッド(add, update, delete)を完成させてください。 + +- **getAll() メソッドは実装済み**なので、参考にしてください。 +- TODOコメントが実装のヒントになっています。 +- 各メソッドの詳細な仕様は後述の「各メソッド説明」を確認してください。 + +### 利用可能なメソッド +- `$this->readData()`: CSVから全データを読み込む(BaseAccessから継承) +- `$this->writeData($data)`: CSVにデータを書き込む(BaseAccessから継承) +- `$this->generateId($rows)`: 新しいIDを生成(privateメソッド) +- `$this->validateEmployeeData($data)`: データバリデーション(privateメソッド) +- `$this->convertRowToEmployee($row)`: CSV行を連想配列に変換(privateメソッド) + +**困ったときは `ヒント.txt` を参照してください。** + + +## 各メソッド説明 +- **getAll()** (実装済み) + 全社員情報を取得して連想配列の配列で返す。 + +- **add($data)** + 新規社員を登録する。IDは自動生成。 + $data = ['name' => '田中五郎', 'email' => 'tanaka@example.com'] + +- **update($id, $data)** + 指定IDの社員情報を更新する。 + IDが存在しない場合は `RuntimeException` をスロー。 + +- **delete($id)** + 指定IDの社員を削除する。 + IDが存在しない場合は `RuntimeException` をスロー。 + + + +## カプセル化のポイント +- **privateメソッド**: `validateEmployeeData()`, `convertRowToEmployee()`, `generateId()` は内部処理のためprivateで定義されています。 +- **protectedプロパティ**: `$file` は継承クラスからのみアクセス可能なprotectedで定義されています。 +- **publicメソッド**: 外部から呼び出す必要があるメソッドのみがpublicで定義されています。 + +## 例外処理のポイント +- **InvalidArgumentException**: 入力データが不正な場合(必須項目が空、メールアドレス形式が不正など) +- **RuntimeException**: ファイル操作やデータ操作に失敗した場合(ファイルが開けない、IDが見つからないなど) +- controller.phpでは、これらの例外をキャッチしてユーザーに分かりやすいエラーメッセージを表示します。 diff --git a/database/abstracts/BaseAccess.php b/database/abstracts/BaseAccess.php new file mode 100644 index 0000000..bc22a28 --- /dev/null +++ b/database/abstracts/BaseAccess.php @@ -0,0 +1,103 @@ +file = $file; + } + + /** + * CSVファイルから全データを読み込む + * カプセル化: protectedで外部から直接呼び出せない + * @return array CSVデータの配列 + * @throws RuntimeException ファイル読み込みに失敗した場合 + */ + protected function readData() + { + if (!file_exists($this->file)) { + return array(); + } + + $handle = fopen($this->file, "r"); + if ($handle === false) { + throw new RuntimeException("ファイルを開けませんでした: " . $this->file); + } + + try { + $data = array(); + while ($row = fgetcsv($handle)) { + // 空行や必要列数が足りない場合はスキップ + if (empty($row) || count($row) < 3) { + continue; + } + $data[] = $row; + } + return $data; + } finally { + fclose($handle); + } + } + + /** + * CSVファイルにデータを書き込む + * カプセル化: protectedで外部から直接呼び出せない + * @param array $data 書き込むデータの配列 + * @return bool 書き込み成功時true + * @throws RuntimeException ファイル書き込みに失敗した場合 + */ + protected function writeData($data) + { + if (!is_array($data)) { + throw new InvalidArgumentException("書き込むデータは配列である必要があります"); + } + + // ディレクトリが存在しない場合は作成 + $directory = dirname($this->file); + if (!is_dir($directory)) { + if (!mkdir($directory, 0755, true)) { + throw new RuntimeException("ディレクトリを作成できませんでした: " . $directory); + } + } + + $handle = fopen($this->file, "w"); + if ($handle === false) { + throw new RuntimeException("ファイルに書き込めませんでした: " . $this->file); + } + + try { + foreach ($data as $row) { + if (fputcsv($handle, $row) === false) { + throw new RuntimeException("CSVデータの書き込みに失敗しました"); + } + } + return true; + } finally { + fclose($handle); + } + } + + /** + * ファイルパスを取得(カプセル化: 読み取り専用アクセサ) + * @return string ファイルパス + */ + public function getFilePath() + { + return $this->file; + } +} diff --git a/database/employees/EmployeeAccess.php b/database/employees/EmployeeAccess.php new file mode 100644 index 0000000..5ba5863 --- /dev/null +++ b/database/employees/EmployeeAccess.php @@ -0,0 +1,174 @@ +readData(); + $employees = array(); + + // 各行のデータを 'id', 'name', 'email' の連想配列に変換する + foreach ($rows as $row) { + $employees[] = $this->convertRowToEmployee($row); + } + + return $employees; + } catch (Exception $e) { + throw new RuntimeException("社員情報の取得に失敗しました: " . $e->getMessage(), 0, $e); + } + } + + /** + * 新規登録(INSERT) + * @param array $data ['name' => '...', 'email' => '...'] の連想配列 + * @return bool 登録成功時true + * @throws InvalidArgumentException データが不正な場合 + * @throws RuntimeException データ書き込みに失敗した場合 + */ + public function add($data) + { + // カプセル化: バリデーションロジックをprivateメソッドで隠蔽 + $this->validateEmployeeData($data); + + try { + // TODO:既存データを取得 + + // TODO:新しいIDを生成 + + // TODO:CSVファイルに新規データを追加する処理 + + // CSVファイルに書き込み + return $this->writeData(); + } catch (Exception $e) { + throw new RuntimeException("社員情報の登録に失敗しました: " . $e->getMessage(), 0, $e); + } + } + + /** + * 更新(UPDATE) + * @param string|int $id 更新する社員のID + * @param array $data ['name' => '...', 'email' => '...'] の連想配列 + * @return bool 更新成功時true + * @throws InvalidArgumentException データが不正な場合 + * @throws RuntimeException データ書き込みに失敗した場合、またはIDが見つからない場合 + */ + public function update($id, $data) + { + // カプセル化: バリデーションロジックをprivateメソッドで隠蔽 + $this->validateEmployeeData($data); + + // IDが指定されていない場合はエラー + if (empty($id)) { + throw new InvalidArgumentException("IDが指定されていません"); + } + + try { + // CSVファイルから全データを取得 + $rows = $this->readData(); + + // 指定されたIDの社員が見つかったかをフラグで管理 + $found = false; + + // TODO: foreachを使い、$rows の各行を参照渡しでチェックして、$id と一致する行の 'name' と 'email' を更新する + // TODO: 見つかったらフラグを立てる + // TODO: 見つからなければエラー + + + + + // 見つからなければエラー + if (!$found) { + throw new RuntimeException("指定されたIDの社員が見つかりません: " . $id); + } + + // CSVファイルに書き込み + return $this->writeData($rows); + } catch (RuntimeException $e) { + throw $e; + } catch (Exception $e) { + throw new RuntimeException("社員情報の更新に失敗しました: " . $e->getMessage(), 0, $e); + } + } + + /** + * 削除(DELETE) + * @param string|int $id 削除する社員のID + * @return bool 削除成功時true + * @throws InvalidArgumentException IDが指定されていない場合 + * @throws RuntimeException データ書き込みに失敗した場合、またはIDが見つからない場合 + */ + public function delete($id) + { + // TODO: ゼロから実装しましょう + } + + /** + * CSV行データを社員情報の連想配列に変換する(カプセル化: privateメソッド) + * @param array $row CSVの1行データ + * @return array ['id' => ..., 'name' => ..., 'email' => ...] の連想配列 + */ + private function convertRowToEmployee($row) + { + return array( + 'id' => isset($row[0]) ? $row[0] : '', + 'name' => isset($row[1]) ? $row[1] : '', + 'email' => isset($row[2]) ? $row[2] : '' + ); + } + + /** + * 社員データのバリデーション(カプセル化: privateメソッド) + * @param array $data バリデーション対象のデータ + * @throws InvalidArgumentException データが不正な場合 + */ + private function validateEmployeeData($data) + { + if (!is_array($data)) { + throw new InvalidArgumentException("データは配列である必要があります"); + } + + if (!isset($data['name']) || empty(trim($data['name']))) { + throw new InvalidArgumentException("名前が指定されていません"); + } + + if (!isset($data['email']) || empty(trim($data['email']))) { + throw new InvalidArgumentException("メールアドレスが指定されていません"); + } + + // メールアドレスの形式チェック + if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) { + throw new InvalidArgumentException("メールアドレスの形式が正しくありません"); + } + } + + /** + * 新しいIDを生成する(カプセル化: privateメソッド) + * @param array $rows 既存のデータ行 + * @return string 生成されたID + */ + private function generateId($rows) + { + // 既存のIDの最大値を取得して+1する方式 + $maxId = 0; + foreach ($rows as $row) { + if (isset($row[0]) && is_numeric($row[0])) { + $maxId = max($maxId, (int)$row[0]); + } + } + return (string)($maxId + 1); + } +} diff --git a/database/interfaces/DataAccessInterface.php b/database/interfaces/DataAccessInterface.php new file mode 100644 index 0000000..aec69a6 --- /dev/null +++ b/database/interfaces/DataAccessInterface.php @@ -0,0 +1,8 @@ +getAll(); + $employees = array(); + if ($keyword != "") { + foreach ($allEmployees as $emp) { + if (strpos($emp['name'], $keyword) !== false) { + $employees[] = $emp; + } + } + } else { + $employees = $allEmployees; + } + include 'employee_list.php'; + } catch (Exception $e) { + $errorMessage = "社員一覧の取得に失敗しました: " . $e->getMessage(); + include 'employee_list.php'; + } + } elseif ($action == 'register') { + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + try { + $name = isset($_POST['name']) ? trim($_POST['name']) : ''; + $email = isset($_POST['email']) ? trim($_POST['email']) : ''; + + if ($name != '' && $email != '') { + $employeeAccess->add(array('name' => $name, 'email' => $email)); + header("Location: controller.php?action=list"); + exit; + } else { + $errorMessage = "名前とメールアドレスは必須です"; + } + } catch (InvalidArgumentException $e) { + $errorMessage = $e->getMessage(); + } catch (Exception $e) { + $errorMessage = "登録に失敗しました: " . $e->getMessage(); + } + } + include 'employee_register.php'; + } elseif ($action == 'update') { + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + try { + $id = isset($_POST['id']) ? $_POST['id'] : ''; + $name = isset($_POST['name']) ? trim($_POST['name']) : ''; + $email = isset($_POST['email']) ? trim($_POST['email']) : ''; + + if ($id != '' && $name != '' && $email != '') { + $employeeAccess->update($id, array('name' => $name, 'email' => $email)); + header("Location: controller.php?action=list"); + exit; + } else { + $errorMessage = "ID、名前、メールアドレスは必須です"; + } + } catch (InvalidArgumentException $e) { + $errorMessage = $e->getMessage(); + } catch (RuntimeException $e) { + $errorMessage = $e->getMessage(); + } catch (Exception $e) { + $errorMessage = "更新に失敗しました: " . $e->getMessage(); + } + include 'employee_update.php'; + } else { + try { + $id = isset($_GET['id']) ? $_GET['id'] : ''; + if (empty($id)) { + $errorMessage = "IDが指定されていません"; + include 'employee_update.php'; + } else { + $employees = $employeeAccess->getAll(); + $employee = null; + foreach ($employees as $emp) { + if ($emp['id'] == $id) { + $employee = $emp; + break; + } + } + if ($employee === null) { + $errorMessage = "指定された社員が見つかりません"; + } + include 'employee_update.php'; + } + } catch (Exception $e) { + $errorMessage = "社員情報の取得に失敗しました: " . $e->getMessage(); + include 'employee_update.php'; + } + } + } elseif ($action == 'delete' && isset($_GET['id'])) { + try { + $id = $_GET['id']; + if (empty($id)) { + throw new InvalidArgumentException("IDが指定されていません"); + } + $employeeAccess->delete($id); + header("Location: controller.php?action=list"); + exit; + } catch (InvalidArgumentException $e) { + $errorMessage = $e->getMessage(); + include 'employee_list.php'; + } catch (RuntimeException $e) { + $errorMessage = $e->getMessage(); + header("Location: controller.php?action=list&error=" . urlencode($errorMessage)); + exit; + } catch (Exception $e) { + $errorMessage = "削除に失敗しました: " . $e->getMessage(); + header("Location: controller.php?action=list&error=" . urlencode($errorMessage)); + exit; + } + } else { + include 'index.php'; + } +} catch (Exception $e) { + // 初期化エラーなど、致命的なエラーの場合 + die("システムエラーが発生しました: " . htmlspecialchars($e->getMessage())); +} diff --git a/public/employee_list.php b/public/employee_list.php new file mode 100644 index 0000000..cf2638f --- /dev/null +++ b/public/employee_list.php @@ -0,0 +1,72 @@ + + + + + + 社員一覧 - 社員メンテナンスシステム + + + + + + + + +
+

社員一覧

+ + + + + + + + +
+ +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + +
ID名前Email操作
+ 更新 + 削除 +
+ 新規登録 + ホームに戻る +
+ + + + + \ No newline at end of file diff --git a/public/employee_register.php b/public/employee_register.php new file mode 100644 index 0000000..6455d52 --- /dev/null +++ b/public/employee_register.php @@ -0,0 +1,44 @@ + + + + + + 社員登録 - 社員メンテナンスシステム + + + + + + + + +
+

社員登録

+ + + + +
+
+ + +
+
+ + +
+ + ホームに戻る +
+
+ + + + + \ No newline at end of file diff --git a/public/employee_update.php b/public/employee_update.php new file mode 100644 index 0000000..54de4bd --- /dev/null +++ b/public/employee_update.php @@ -0,0 +1,51 @@ + + + + + + 社員更新 - 社員メンテナンスシステム + + + + + + + + +
+

社員更新

+ + + + + +
+ +
+ + +
+
+ + +
+ + 社員一覧に戻る +
+ + + +
+ + + + + \ No newline at end of file diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..a0a91ef --- /dev/null +++ b/public/index.php @@ -0,0 +1,30 @@ + + + + + + ホーム - 社員メンテナンスシステム + + + + + + + + +
+

ホーム

+ +
+ + + + + \ No newline at end of file diff --git a/ヒント.md b/ヒント.md new file mode 100644 index 0000000..6681f2e --- /dev/null +++ b/ヒント.md @@ -0,0 +1,219 @@ +# EmployeeAccess.php 実装のヒント + +## まず理解すべきこと:「配列の中に配列」 + +CSVファイルは「表形式」のデータです。これをPHPで扱うときは「配列の中に配列を入れる」形になります。 + +### イメージ + +``` +CSVファイル: +1610000001,山田太郎,yamada@gmail.com +1610000002,鈴木花子,suzuki@gmail.com +1610000003,麻枝史明,maeda@gmail.com + +↓ readData()で読み込むと... + +$rows = [ + ['1610000001', '山田太郎', 'yamada@gmail.com'], // 1行目 + ['1610000002', '鈴木花子', 'suzuki@gmail.com'], // 2行目 + ['1610000003', '麻枝史明', 'maeda@gmail.com'] // 3行目 +] +``` + +**重要**: `$rows`は「箱の中に箱が入っている」状態。外側の箱($rows)の中に、3つの小さな箱(各行)が入っている。 + +--- + +## add(新規登録)の考え方 + +### 質問:既にある配列に、新しい1行を追加するには? + +``` +今のCSVファイル($rows): +['1610000001', '山田太郎', 'yamada@gmail.com'] +['1610000002', '鈴木花子', 'suzuki@gmail.com'] +['1610000003', '麻枝史明', 'maeda@gmail.com'] + +↓ ここに新しい行を追加したい! + +['1610000004', '田中五郎', 'tanaka@example.com'] ← これを追加 +``` + +### 考え方の手順 + +1. **まず「箱の中身」を全部取り出す** + → `$rows = $this->readData();` + → 今、`$rows`には既存の3行が入っている + +2. **新しい1行(箱)を作る** + → 新しいID、名前、メールアドレスを1つの配列にする + → `$newRow = [新しいID, 新しい名前, 新しいメールアドレス];` + +3. **大きな箱($rows)の一番後ろに、小さな箱($newRow)を入れる** + → `$rows[] = $newRow;` + → これで$rowsには4行になる! + +4. **箱の中身をCSVファイルに全部書き戻す** + → `$this->writeData($rows);` + +### なぜ `$rows[] = $newRow;` と書くのか? + +**`配列[] = 値;` は「配列の最後に追加する」という意味** + +```php +$arr = [1, 2, 3]; +$arr[] = 4; +// 結果: $arr = [1, 2, 3, 4] + +$fruits = ['りんご', 'バナナ']; +$fruits[] = 'みかん'; +// 結果: $fruits = ['りんご', 'バナナ', 'みかん'] +``` + +CSVの場合も同じ: + +```php +$rows = [ + ['1', '山田', 'yamada@example.com'], + ['2', '鈴木', 'suzuki@example.com'] +]; + +$newRow = ['3', '田中', 'tanaka@example.com']; +$rows[] = $newRow; // ← 最後に追加! + +// 結果: +$rows = [ + ['1', '山田', 'yamada@example.com'], + ['2', '鈴木', 'suzuki@example.com'], + ['3', '田中', 'tanaka@example.com'] // ← 追加された +]; +``` + +**つまり**: 新しい行(箱)を、全体の配列(大きな箱)の最後にポンと入れるイメージ。 + +--- + +## update(更新)の考え方 + +### 質問:既にある行の、特定の項目だけを変更するには? + +``` +今のCSVファイル: +['1610000001', '山田太郎', 'yamada@gmail.com'] +['1610000002', '鈴木花子', 'suzuki@gmail.com'] ← この行の名前とメールを変更したい +['1610000003', '麻枝史明', 'maeda@gmail.com'] + +↓ + +['1610000001', '山田太郎', 'yamada@gmail.com'] +['1610000002', '鈴木次郎', 'suzuki_new@example.com'] ← 変更された! +['1610000003', '麻枝史明', 'maeda@gmail.com'] +``` + +### 考え方の手順 + +1. **箱の中身を全部取り出す** + → `$rows = $this->readData();` + +2. **1つずつ箱を開けて、目的のIDか確認する** + → forループで `$rows[0]`, `$rows[1]`, `$rows[2]` ... と順番に見ていく + → 各行の `$rows[$i][0]` がID + +3. **目的のIDが見つかったら、その行の名前とメールを上書きする** + → `$rows[$i][1] = 新しい名前;` + → `$rows[$i][2] = 新しいメールアドレス;` + +4. **見つかったらフラグを立てる** + → `$found = true;` + +5. **ループ後、見つからなければエラー** + → `if (!$found) throw new RuntimeException(...);` + +6. **箱の中身をCSVファイルに全部書き戻す** + → `$this->writeData($rows);` + +### 配列の要素を変更する方法 + +配列の中身を変更したい場合、いくつかの方法があります: + +```php +// 方法1: for文でインデックスを使う +for ($i = 0; $i < count($rows); $i++) { + if ($rows[$i][0] == '検索したいID') { + $rows[$i][1] = '新しい名前'; // インデックスで直接変更 + } +} + +// 方法2: foreachで参照渡し(&を使う) +foreach ($rows as &$row) { + if ($row[0] == '検索したいID') { + $row[1] = '新しい名前'; // &があるので元の配列が変わる + } +} +unset($row); // 重要: 参照を切断しないと、後で$rowを使ったときに元の配列が意図せず書き換わる + +// 方法3: foreachでキーを使う +foreach ($rows as $key => $row) { + if ($row[0] == '検索したいID') { + $rows[$key][1] = '新しい名前'; // キーで元の配列にアクセス + } +} +``` + +**注意**: 普通の `foreach ($rows as $row)` だと、`$row`はコピーなので元の`$rows`は変わりません。 + +--- + +## delete(削除)の考え方 + +### 質問:特定の行だけを除外した新しい配列を作るには? + +``` +今のCSVファイル: +['1610000001', '山田太郎', 'yamada@gmail.com'] +['1610000002', '鈴木花子', 'suzuki@gmail.com'] ← この行を削除したい +['1610000003', '麻枝史明', 'maeda@gmail.com'] + +↓ + +['1610000001', '山田太郎', 'yamada@gmail.com'] +['1610000003', '麻枝史明', 'maeda@gmail.com'] ← 2行だけ残った +``` + +### 考え方の手順 + +1. **箱の中身を全部取り出す** + → `$rows = $this->readData();` + +2. **新しい空の箱を用意する** + → `$newRows = [];` + +3. **1つずつ箱を開けて、削除対象じゃないものだけを新しい箱に入れる** + → foreachで各行をチェック + → IDが一致したら `continue;`(スキップ) + → 一致しなければ `$newRows[] = $row;`(新しい箱に入れる) + +4. **見つかったらフラグを立てる** + → `$found = true;` + +5. **ループ後、見つからなければエラー** + → `if (!$found) throw new RuntimeException(...);` + +6. **新しい箱の中身をCSVファイルに書き込む** + → `$this->writeData($newRows);` + +### なぜ `continue;` を使うのか? + +**「この行は無視して次へ」という意味** + +```php +foreach ($rows as $row) { + if ($row[0] == '削除したいID') { + continue; // ← ここで次のループへジャンプ。以下の処理はスキップされる + } + $newRows[] = $row; // ← 削除対象じゃない行だけここに到達する +} +``` + +**つまり**: 削除対象の行は「新しい箱に入れない」ことで削除を実現する。 diff --git a/仕様書/単体テスト仕様書.xlsx b/仕様書/単体テスト仕様書.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..bc51b792b5ab06f640be3ac8b6369835a74d395e GIT binary patch literal 31667 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�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