no message

This commit is contained in:
a-kizaki
2026-10-22 08:48:13 +09:00
commit f81638a7b3
13 changed files with 934 additions and 0 deletions

View File

@@ -0,0 +1,103 @@
<?php
/**
* CSVファイル操作の基底クラス
* カプセル化: ファイル操作の詳細をprotectedメソッドで隠蔽
*/
abstract class BaseAccess
{
/** @var string CSVファイルのパス(カプセル化: protectedで継承クラスのみアクセス可能) */
protected $file;
/**
* コンストラクタ
* @param string $file CSVファイルのパス
* @throws InvalidArgumentException ファイルパスが無効な場合
*/
public function __construct($file)
{
if (empty($file)) {
throw new InvalidArgumentException("ファイルパスが指定されていません");
}
$this->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;
}
}

View File

@@ -0,0 +1,174 @@
<?php
require_once __DIR__ . '/../abstracts/BaseAccess.php';
require_once __DIR__ . '/../interfaces/DataAccessInterface.php';
/**
* 社員情報のCSV操作を実装したクラス
* カプセル化: バリデーションやデータ変換ロジックをprivateメソッドで隠蔽
*/
class EmployeeAccess extends BaseAccess implements DataAccessInterface
{
/**
* 全社員情報を取得する(実装済み)
* @return array 社員情報の連想配列の配列
* @throws RuntimeException データ読み込みに失敗した場合
*/
public function getAll()
{
try {
// BaseAccess の readData() を利用してCSVファイルから全データを取得
$rows = $this->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);
}
}

View File

@@ -0,0 +1,8 @@
<?php
interface DataAccessInterface
{
public function getAll();
public function add($data);
public function update($id, $data);
public function delete($id);
}