# 機能設計書 33-クラウドストレージ

## 概要

本ドキュメントは、Laravel Frameworkにおけるクラウドストレージ（Cloud Storage）機能の設計書である。Flysystemライブラリをベースに、複数のストレージドライバを統一インターフェースで管理し、Local、S3、FTP、SFTPなど様々なストレージサービスへの透過的なアクセスを提供する。

### 本機能の処理概要

**業務上の目的・背景**：
現代のWebアプリケーションでは、ユーザーアップロードファイル、静的アセット、バックアップデータなどを様々なストレージサービスに保存する必要がある。本機能は、ストレージの種類（ローカル、クラウド）に関わらず、統一されたAPIでファイル操作を行えるようにし、ストレージ切り替え時のコード変更を最小限に抑える。これにより、開発環境ではローカルストレージ、本番環境ではS3というような柔軟な構成が可能となる。

**機能の利用シーン**：
- ユーザーアップロードファイルのS3保存
- 静的アセットのCDN配信用ストレージ管理
- データベースバックアップのクラウド保存
- 複数ディスク間でのファイル移動・コピー
- 一時URLによる期限付きファイルアクセス提供

**主要な処理内容**：
1. ディスク管理（`disk`, `drive`, `cloud`メソッドによるディスクインスタンス取得）
2. ファイル読み書き（`get`, `put`, `putFile`, `putFileAs`メソッド）
3. ファイル情報取得（`exists`, `size`, `mimeType`, `lastModified`メソッド）
4. ファイル操作（`copy`, `move`, `delete`メソッド）
5. ディレクトリ操作（`files`, `directories`, `makeDirectory`, `deleteDirectory`メソッド）
6. URL生成（`url`, `temporaryUrl`, `temporaryUploadUrl`メソッド）
7. カスタムドライバ登録（`extend`メソッドによるドライバ拡張）

**関連システム・外部連携**：
- AWS S3: Amazon S3ストレージサービス
- FTP/SFTP: ファイル転送プロトコル対応サーバー
- Cloudflare R2: S3互換ストレージ
- Flysystem: PHPファイルシステム抽象化ライブラリ

**権限による制御**：
ファイルのvisibility（public/private）設定により、アクセス制御を行う。各ストレージサービス固有の権限設定は設定ファイルで管理する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はバックエンド処理のため、直接関連する画面はない |

## 機能種別

ファイル管理 / クラウド連携 / ストレージ抽象化

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| path | string | Yes | ファイルパス（相対パス） | - |
| contents | string\|resource\|StreamInterface | Yes（書き込み時） | ファイル内容 | - |
| options | array | No | 可視性、メタデータ等のオプション | - |
| visibility | string | No | 'public' または 'private' | public/private |

### 入力データソース

- 設定ファイル（`config/filesystems.php`）
- アプリケーションコードからの直接呼び出し
- アップロードファイル（`Illuminate\Http\UploadedFile`）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| contents | string | ファイル内容 |
| exists | bool | 存在確認結果 |
| url | string | ファイルのパブリックURL |
| temporaryUrl | string | 一時的なアクセスURL |
| files | array | ファイルパス一覧 |
| directories | array | ディレクトリパス一覧 |

### 出力先

- 設定されたストレージサービス
- 戻り値として呼び出し元に返却

## 処理フロー

### 処理シーケンス

```
1. ディスク取得（disk呼び出し）
   └─ ディスク名を受け取る（nullの場合はデフォルト）

2. キャッシュ確認
   └─ 既に解決済みのディスクがあればそれを返却

3. ディスク解決
   └─ 設定からドライバ情報を取得
   └─ カスタムドライバまたは標準ドライバを選択
   └─ 対応するcreate{Driver}Driverメソッドを呼び出し

4. アダプタ作成
   └─ Flysystemアダプタを設定に基づき作成
   └─ read-onlyラッパー、prefixラッパーの適用

5. FilesystemAdapterでラップ
   └─ Laravel固有の機能を追加
   └─ ディスクインスタンスをキャッシュに保存

6. ファイル操作
   └─ FilesystemAdapterを通じてFlysystemを操作
```

### フローチャート

```mermaid
flowchart TD
    A[Storage::disk呼び出し] --> B{ディスク名指定?}
    B -->|No| C[デフォルトドライバ取得]
    B -->|Yes| D[指定ディスク名使用]
    C --> E{キャッシュに存在?}
    D --> E
    E -->|Yes| F[キャッシュから返却]
    E -->|No| G[設定からドライバ取得]
    G --> H{カスタムドライバ?}
    H -->|Yes| I[カスタムクリエーター呼び出し]
    H -->|No| J{ドライバ種別}
    J -->|local| K[LocalAdapter作成]
    J -->|s3| L[S3Adapter作成]
    J -->|ftp| M[FtpAdapter作成]
    J -->|sftp| N[SftpAdapter作成]
    J -->|scoped| O[ScopedDriver作成]
    I --> P[FilesystemAdapter作成]
    K --> P
    L --> P
    M --> P
    N --> P
    O --> P
    P --> Q[キャッシュに保存]
    Q --> R[ディスクインスタンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-33-01 | デフォルトディスク | ディスク名未指定時はconfig設定のデフォルトを使用 | disk(null)呼び出し時 |
| BR-33-02 | ディスクキャッシュ | 同一ディスクは再解決せずキャッシュを使用 | 2回目以降のdisk呼び出し |
| BR-33-03 | 可視性デフォルト | 未指定時のvisibilityはprivate | visibility未設定時 |
| BR-33-04 | S3 URL形式 | S3のURLはバケットとリージョンに基づき生成 | S3ドライバ使用時 |
| BR-33-05 | 一時URL期限 | temporaryUrlは指定した有効期限で署名URL生成 | temporaryUrl呼び出し時 |

### 計算ロジック

**一時URL生成（S3の場合）**:
AWS SDKのgetCommand + createPresignedRequestを使用し、署名付きURLを生成。

## データベース操作仕様

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | InvalidArgumentException | 未設定のドライバ指定 | config/filesystems.phpを確認 |
| - | UnableToReadFile | ファイル読み込み失敗 | パスとパーミッションを確認 |
| - | UnableToWriteFile | ファイル書き込み失敗 | パスとパーミッションを確認 |
| - | RuntimeException | 一時URL非対応ドライバ | 対応ドライバに変更またはカスタム実装 |

### リトライ仕様

本機能にリトライ機能は含まれない。ネットワーク経由のストレージアクセス時はアプリケーション側でリトライを実装する。

## トランザクション仕様

ファイルシステム操作はデータベーストランザクションに含まれない。複数ファイル操作時の原子性は保証されない。

## パフォーマンス要件

- ディスクインスタンスはリクエスト内でキャッシュされ、再接続を回避
- S3等のクラウドストレージはネットワークレイテンシを考慮
- 大きなファイルはストリーミング処理（`readStream`, `writeStream`）を推奨
- Cloudflare R2使用時は`retain_visibility = false`を自動設定

## セキュリティ考慮事項

- S3認証情報は環境変数で管理し、コードにハードコードしない
- プライベートファイルには一時URLを使用し、直接URLを公開しない
- アップロードファイルのMIMEタイプ検証を行う
- パストラバーサル攻撃を防ぐため、ユーザー入力のパス検証を行う

## 備考

- Macroableトレイトにより、FilesystemAdapterにカスタムメソッドを追加可能
- `throw`オプションでFlysystem例外の伝播制御が可能
- `report`オプションでエラーを例外ハンドラに報告可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: インターフェースを理解する

まず、Filesystemの契約を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Factory.php | `src/Illuminate/Contracts/Filesystem/Factory.php` | FilesystemManagerが実装するインターフェース |
| 1-2 | Filesystem.php | `src/Illuminate/Contracts/Filesystem/Filesystem.php` | 各ディスクが実装するインターフェース |

#### Step 2: FilesystemManagerを理解する

ディスク管理の中核クラスを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FilesystemManager.php | `src/Illuminate/Filesystem/FilesystemManager.php` | ディスク管理、ドライバ作成 |

**主要処理フロー**:
- **69-72行目**: `drive()` - disk()へのエイリアス
- **80-85行目**: `disk()` - ディスクインスタンス取得のエントリーポイント
- **119-122行目**: `get()` - キャッシュ確認と解決
- **133-154行目**: `resolve()` - ドライバ解決のメインロジック
- **174-197行目**: `createLocalDriver()` - ローカルドライバ作成
- **243-262行目**: `createS3Driver()` - S3ドライバ作成
- **333-355行目**: `createFlysystem()` - Flysystemインスタンス作成
- **437-442行目**: `extend()` - カスタムドライバ登録

**読解のコツ**: FilesystemManagerはManagerパターンを実装しており、`create{Driver}Driver`メソッドが各ドライバの作成を担当する。新しいドライバを追加する場合は`extend`メソッドを使用する。

#### Step 3: FilesystemAdapterを理解する

実際のファイル操作を行うアダプタを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FilesystemAdapter.php | `src/Illuminate/Filesystem/FilesystemAdapter.php` | Flysystemラッパー、Laravel固有機能 |

**主要処理フロー**:
- **107-119行目**: コンストラクタ - Flysystemドライバとアダプタの保持
- **216-220行目**: `exists()` - ファイル存在確認
- **293-302行目**: `get()` - ファイル内容取得
- **403-436行目**: `put()` - ファイル書き込み
- **564-584行目**: `delete()` - ファイル削除
- **731-750行目**: `url()` - URL生成
- **822-835行目**: `temporaryUrl()` - 一時URL生成

#### Step 4: サービスプロバイダーを理解する

コンテナ登録を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FilesystemServiceProvider.php | `src/Illuminate/Filesystem/FilesystemServiceProvider.php` | サービス登録とファイル配信 |

**主要処理フロー**:
- **50-61行目**: `registerFlysystem()` - FilesystemManagerとデフォルトディスクの登録
- **68-73行目**: `registerManager()` - `filesystem`としてシングルトン登録
- **80-115行目**: `serveFiles()` - ローカルファイル配信ルートの登録

### プログラム呼び出し階層図

```
Storage::disk('s3')
    │
    └─ FilesystemManager::disk('s3')
           │
           ├─ get('s3') ... キャッシュ確認
           │      └─ disks['s3'] が存在すれば返却
           │
           └─ resolve('s3')
                  │
                  ├─ getConfig('s3') ... 設定取得
                  │
                  ├─ customCreators確認
                  │      └─ callCustomCreator()
                  │
                  └─ createS3Driver($config)
                         │
                         ├─ formatS3Config() ... 認証情報整形
                         │
                         ├─ S3Client作成
                         │
                         ├─ S3Adapter作成
                         │
                         └─ AwsS3V3Adapter作成（FilesystemAdapterのサブクラス）

Storage::put('path', 'content')
    │
    └─ FilesystemAdapter::put('path', 'content', [])
           │
           ├─ UploadedFile/File判定
           │      └─ putFile()経由で処理
           │
           └─ driver->write() or driver->writeStream()
                  └─ Flysystem\Filesystem::write()
```

### データフロー図

```
[入力]                    [処理]                           [出力]

ディスク名 ──────────────▶ FilesystemManager::disk()
                               │
                         設定読み込み
                               │
                         ドライバ解決
                               │
                    FilesystemAdapter◀──┘

パス + 内容 ──────────────▶ FilesystemAdapter::put()
                               │
                         Flysystem::write()
                               │
                         ┌─────┴─────┐
                         │           │
                       ローカル    クラウド
                         │           │
                    ファイル作成   API呼び出し
                         │           │
                    true/false ◀───┴────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FilesystemManager.php | `src/Illuminate/Filesystem/FilesystemManager.php` | ソース | ディスク管理の中核クラス |
| FilesystemAdapter.php | `src/Illuminate/Filesystem/FilesystemAdapter.php` | ソース | Flysystemラッパー |
| LocalFilesystemAdapter.php | `src/Illuminate/Filesystem/LocalFilesystemAdapter.php` | ソース | ローカル専用拡張 |
| AwsS3V3Adapter.php | `src/Illuminate/Filesystem/AwsS3V3Adapter.php` | ソース | S3専用拡張 |
| FilesystemServiceProvider.php | `src/Illuminate/Filesystem/FilesystemServiceProvider.php` | ソース | サービスプロバイダー |
| Factory.php | `src/Illuminate/Contracts/Filesystem/Factory.php` | インターフェース | Manager契約 |
| Filesystem.php | `src/Illuminate/Contracts/Filesystem/Filesystem.php` | インターフェース | Disk契約 |
| Cloud.php | `src/Illuminate/Contracts/Filesystem/Cloud.php` | インターフェース | クラウドディスク契約 |
