# 機能設計書 14-Dotenv

## 概要

本ドキュメントは、Symfony Dotenvコンポーネントの機能設計を記述する。Dotenvは.envファイルから環境変数を登録する機能を提供し、開発環境での環境変数管理を容易にする。

### 本機能の処理概要

**業務上の目的・背景**：アプリケーションの設定を環境変数で管理する「12 Factor App」の原則に従い、データベース接続情報やAPIキー等の環境依存設定を.envファイルで管理する。これにより、コードと設定の分離を実現し、環境ごとの設定切り替えを容易にする。

**機能の利用シーン**：開発環境でのアプリケーション起動時（bootEnv/loadEnv）、テスト環境での環境変数設定、.envファイルの構文解析、環境変数のオーバーライドに利用される。

**主要な処理内容**：
1. .envファイルの読み込みとパース（load、parse）
2. 環境別.envファイルの階層的読み込み（loadEnv）
3. 起動時の最適化読み込み（bootEnv、.env.local.php対応）
4. 環境変数の登録（populate）
5. 変数展開とコマンド展開（resolveVariables、resolveCommands）
6. 字句解析（lexVarname、lexValue）

**関連システム・外部連携**：Processコンポーネント（コマンド展開時のシェル実行）、FrameworkBundle（アプリケーションブートストラップ）と連携する。

**権限による制御**：本コンポーネント自体は権限制御を行わない。APP_ENVとAPP_DEBUGの環境変数によりアプリケーション全体のモード制御に寄与する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （直接的な関連画面なし） | - | 環境変数として各画面・コンポーネントに間接的に影響 |

## 機能種別

設定読み込み / 環境変数管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| path | string | Yes | .envファイルのパス | ファイルが読み取り可能であること |
| envKey | string | No | 環境名を格納する変数名（デフォルト: APP_ENV） | 文字列 |
| debugKey | string | No | デバッグフラグを格納する変数名（デフォルト: APP_DEBUG） | 文字列 |
| defaultEnv | string | No | デフォルト環境名（デフォルト: dev） | 文字列 |
| testEnvs | array | No | .env.localを無視するテスト環境名リスト（デフォルト: ['test']） | 文字列配列 |
| overrideExistingVars | bool | No | 既存環境変数を上書きするか（デフォルト: false） | boolean値 |

### 入力データソース

.envファイル（.env、.env.local、.env.{env}、.env.{env}.local）、.env.local.php（キャッシュ済み環境変数）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| $_ENV | array | 登録された環境変数（$_ENVスーパーグローバル） |
| $_SERVER | array | 登録された環境変数（$_SERVERスーパーグローバル） |
| SYMFONY_DOTENV_VARS | string | Dotenvで登録した変数名のカンマ区切りリスト |
| SYMFONY_DOTENV_PATH | string | 読み込んだ.envファイルのパス |

### 出力先

PHPスーパーグローバル変数（$_ENV、$_SERVER）、putenv（オプション）

## 処理フロー

### 処理シーケンス

```
1. bootEnv呼び出し
   └─ .env.local.phpの存在チェックと読み込み試行
2. .env.local.phpが有効な場合
   └─ populateで環境変数を一括登録
3. .env.local.phpが無効な場合 → loadEnv呼び出し
   └─ 3a. .envファイル読み込み（なければ.env.dist）
   └─ 3b. APP_ENV決定（未設定ならdefaultEnv）
   └─ 3c. .env.local読み込み（テスト環境以外）
   └─ 3d. .env.{env}読み込み
   └─ 3e. .env.{env}.local読み込み
4. APP_DEBUG設定
   └─ prodEnvsに含まれる場合はfalse、それ以外はtrue
```

### フローチャート

```mermaid
flowchart TD
    A[bootEnv] --> B{.env.local.php存在?}
    B -->|Yes| C[includeで読み込み]
    C --> D{有効な配列?}
    D -->|Yes| E[populate]
    D -->|No| F[loadEnv]
    B -->|No| F
    F --> G[.env読み込み]
    G --> H{APP_ENV設定済み?}
    H -->|No| I[defaultEnvをセット]
    H -->|Yes| J[既存値を使用]
    I --> K{テスト環境?}
    J --> K
    K -->|No| L[.env.local読み込み]
    K -->|Yes| M[スキップ]
    L --> N[.env.APP_ENV読み込み]
    M --> N
    N --> O[.env.APP_ENV.local読み込み]
    O --> P[APP_DEBUG設定]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-14-01 | テスト環境の.env.local無視 | testEnvsに含まれる環境では.env.localを読み込まない | loadEnv実行時 |
| BR-14-02 | local環境の早期リターン | APP_ENVが'local'の場合、環境別ファイルの読み込みをスキップ | loadEnv実行時 |
| BR-14-03 | 既存変数非上書き | デフォルトではシステムで設定済みの環境変数を上書きしない | populate実行時 |
| BR-14-04 | putenvのスレッド安全性 | putenvはスレッドセーフでないためデフォルト無効 | usePutenv設定 |
| BR-14-05 | BOMファイル拒否 | BOM付きファイルの読み込みはFormatExceptionで拒否 | doLoad実行時 |
| BR-14-06 | 変数展開 | ${VAR}、${VAR:-default}、${VAR:=default}形式の変数展開をサポート | lexValue/resolveVariables |

### 計算ロジック

APP_DEBUG判定: prodEnvsに現在の環境名が含まれる場合は'0'、それ以外は'1'。filter_var(..., FILTER_VALIDATE_BOOL)で既存値の解釈も行う。

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

### 操作別データベース影響一覧

本コンポーネントはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | PathException | .envファイルが存在しないまたは読み取り不可 | ファイルのパスとパーミッションを確認 |
| - | FormatException | .envファイルの構文エラー | エラーメッセージの行番号・カーソル位置を参考に修正 |
| - | FormatException | BOM付きファイル | BOMを除去して保存 |
| - | LogicException | Windowsでのコマンド展開 | Linux/macOS環境を使用するか、コマンド展開を避ける |
| - | LogicException | Processコンポーネント未インストールでのコマンド展開 | composer require symfony/process |

### リトライ仕様

リトライは行わない。.envファイルの読み込みはアプリケーション起動時に1回実行される。

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

トランザクション管理は行わない。環境変数の登録は即座に反映される。

## パフォーマンス要件

- bootEnvで.env.local.phpが存在する場合、.envファイルのパースをスキップして高速に起動
- .env.local.phpはPHP配列としてincludeされるため、opcacheの恩恵を受ける
- パースはステートマシン方式で実装され、正規表現を最小限に使用

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

- .envファイルにはデータベースパスワードやAPIキー等の機密情報が含まれる可能性がある。Webサーバーの公開ディレクトリに配置しないこと
- putenvの使用はスレッドセーフでないため、マルチスレッド環境では無効にする
- コマンド展開（$(...)）はシェルコマンドの実行を伴うため、信頼できない入力を.envファイルに含めないこと
- HTTP_で始まる変数名は$_SERVERに登録されない（HTTPヘッダーとの衝突防止）

## 備考

- SYMFONY_DOTENV_VARS変数により、Dotenvで登録した変数名を追跡可能
- .env.distファイルは.envが存在しない場合のフォールバックとして使用される
- 変数値のデフォルト値は:-（参照のみ）と:=（代入あり）の2種類をサポート

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Dotenv.php（定数・プロパティ） | `src/Symfony/Component/Dotenv/Dotenv.php` | VARNAME_REGEX、STATE定数、内部状態プロパティ（path、cursor、lineno、data、end、values） |

**読解のコツ**: Dotenvクラスはステートマシンとして実装されている。cursor（現在位置）とlineno（行番号）を進めながらdata（入力文字列）をパースする。STATE_VARNAMEとSTATE_VALUEの2状態を交互に遷移する。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Dotenv.php（bootEnv） | `src/Symfony/Component/Dotenv/Dotenv.php` | bootEnvメソッド（140-158行目）がアプリケーション起動時のメインエントリーポイント |
| 2-2 | Dotenv.php（loadEnv） | `src/Symfony/Component/Dotenv/Dotenv.php` | loadEnvメソッド（99-131行目）が環境別ファイルの階層的読み込み |

**主要処理フロー**:
1. **140-158行目**: bootEnv()。.env.local.php存在チェック、populate/loadEnvの分岐、APP_DEBUG設定
2. **99-131行目**: loadEnv()。.env → .env.local → .env.{env} → .env.{env}.localの順序的読み込み
3. **79-82行目**: load()。doLoadの呼び出し（overrideExistingVars=false）
4. **180-219行目**: populate()。$_ENV/$_SERVER/putenvへの変数登録、SYMFONY_DOTENV_VARSの管理

#### Step 3: パース処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Dotenv.php（parse） | `src/Symfony/Component/Dotenv/Dotenv.php` | parseメソッド（229-266行目）のステートマシン処理 |
| 3-2 | Dotenv.php（lexVarname） | `src/Symfony/Component/Dotenv/Dotenv.php` | 変数名の字句解析（268-294行目） |
| 3-3 | Dotenv.php（lexValue） | `src/Symfony/Component/Dotenv/Dotenv.php` | 値の字句解析。シングルクォート、ダブルクォート、非クォートの3パターン（296-387行目） |

**主要処理フロー**:
- **268-294行目**: lexVarname()。export対応、VARNAME_REGEXによるマッチ、=の確認
- **296-387行目**: lexValue()。3種類のクォーティング処理、変数展開、コマンド展開

#### Step 4: 変数展開・コマンド展開

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Dotenv.php（resolveVariables） | `src/Symfony/Component/Dotenv/Dotenv.php` | 変数展開処理（471-535行目）。${VAR}、${VAR:-default}、${VAR:=default}対応 |
| 4-2 | Dotenv.php（resolveCommands） | `src/Symfony/Component/Dotenv/Dotenv.php` | コマンド展開処理（422-469行目）。$()パターンのシェル実行 |

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

```
Dotenv::bootEnv()
    │
    ├─ include(.env.local.php)
    │      └─ populate()
    │
    └─ loadEnv()
           ├─ doLoad(.env)
           │      ├─ parse()
           │      │      ├─ lexVarname()
           │      │      └─ lexValue()
           │      │             ├─ resolveVariables()
           │      │             └─ resolveCommands()
           │      │                    └─ Process::fromShellCommandline()
           │      └─ populate()
           ├─ doLoad(.env.local)
           ├─ doLoad(.env.{env})
           └─ doLoad(.env.{env}.local)
```

### データフロー図

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

.envファイル群       ───▶ Dotenv::parse()              ───▶ key=value配列
                           │
                           ├─ 変数名パース
                           ├─ 値パース
                           ├─ 変数展開
                           └─ コマンド展開
                                  │
                                  ▼
                    Dotenv::populate()                 ───▶ $_ENV / $_SERVER / putenv
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Dotenv.php | `src/Symfony/Component/Dotenv/Dotenv.php` | ソース | .envファイルパーサー・環境変数ローダー |
| FormatException.php | `src/Symfony/Component/Dotenv/Exception/FormatException.php` | ソース | 構文エラー例外 |
| FormatExceptionContext.php | `src/Symfony/Component/Dotenv/Exception/FormatExceptionContext.php` | ソース | 構文エラーのコンテキスト情報 |
| PathException.php | `src/Symfony/Component/Dotenv/Exception/PathException.php` | ソース | パスエラー例外 |
| Command/ | `src/Symfony/Component/Dotenv/Command/` | ソース | dotenv関連コンソールコマンド |
