# 機能設計書：ヘルパー関数

## 1. 機能概要

### 1.1 機能名
ヘルパー関数（Helper Functions）

### 1.2 機能説明
Laravel アプリケーション開発で頻繁に使用されるユーティリティ関数群。グローバル関数として定義され、値の判定、変換、例外処理などの共通処理を簡潔に記述できる。

### 1.3 関連画面
- なし（全機能で横断的に使用されるユーティリティ）

## 2. 機能詳細

### 2.1 主要ヘルパー関数

#### 値判定関数

| 関数名 | 説明 | 引数 | 戻り値 |
|--------|------|------|--------|
| `blank()` | 値が空かどうか判定 | `$value` | `bool` |
| `filled()` | 値が空でないかどうか判定 | `$value` | `bool` |

#### 文字列操作関数

| 関数名 | 説明 | 引数 | 戻り値 |
|--------|------|------|--------|
| `str()` | Stringable オブジェクト取得 | `$string` | `Stringable\|object` |
| `e()` | HTML エスケープ | `$value, $doubleEncode` | `string` |
| `class_basename()` | クラスのベース名取得 | `$class` | `string` |
| `preg_replace_array()` | パターンを順次置換 | `$pattern, $replacements, $subject` | `string` |

#### オブジェクト操作関数

| 関数名 | 説明 | 引数 | 戻り値 |
|--------|------|------|--------|
| `tap()` | 値にコールバック適用後に値を返却 | `$value, $callback` | `mixed` |
| `with()` | 値をオプションでコールバック経由で返却 | `$value, $callback` | `mixed` |
| `transform()` | 値が空でなければ変換 | `$value, $callback, $default` | `mixed` |
| `optional()` | null許容オブジェクトラッパー | `$value, $callback` | `Optional\|mixed` |
| `fluent()` | Fluent オブジェクト作成 | `$value` | `Fluent` |
| `literal()` | リテラルオブジェクト作成 | `...$arguments` | `mixed` |
| `object_get()` | ドット記法でオブジェクトから値取得 | `$object, $key, $default` | `mixed` |

#### 環境・設定関数

| 関数名 | 説明 | 引数 | 戻り値 |
|--------|------|------|--------|
| `env()` | 環境変数取得 | `$key, $default` | `mixed` |
| `windows_os()` | Windows 環境判定 | - | `bool` |
| `laravel_cloud()` | Laravel Cloud 環境判定 | - | `bool` |

#### トレイト・クラス操作関数

| 関数名 | 説明 | 引数 | 戻り値 |
|--------|------|------|--------|
| `class_uses_recursive()` | 再帰的にトレイト取得 | `$class` | `array` |
| `trait_uses_recursive()` | トレイトが使用するトレイト取得 | `$trait` | `array` |

#### 例外処理関数

| 関数名 | 説明 | 引数 | 戻り値 |
|--------|------|------|--------|
| `throw_if()` | 条件が真なら例外スロー | `$condition, $exception, ...$parameters` | `mixed` |
| `throw_unless()` | 条件が偽なら例外スロー | `$condition, $exception, ...$parameters` | `mixed` |

#### リトライ関数

| 関数名 | 説明 | 引数 | 戻り値 |
|--------|------|------|--------|
| `retry()` | 失敗時にリトライ実行 | `$times, $callback, $sleepMilliseconds, $when` | `mixed` |

#### キャッシュ関数

| 関数名 | 説明 | 引数 | 戻り値 |
|--------|------|------|--------|
| `once()` | コールバックを一度だけ実行し結果をキャッシュ | `$callback` | `mixed` |

#### 設定関数

| 関数名 | 説明 | 引数 | 戻り値 |
|--------|------|------|--------|
| `append_config()` | 設定配列に追加 | `$array` | `array` |

### 2.2 関数詳細

#### blank() / filled()

```php
// blank() - 以下を空と判定
blank(null);           // true
blank('');             // true
blank('   ');          // true (trimされる)
blank([]);             // true
blank(new Collection); // true

// 以下は空ではない
blank(0);              // false
blank(false);          // false
blank('0');            // false

// filled() は blank() の逆
filled('hello');       // true
filled(null);          // false
```

#### tap()

```php
// 値を操作後、元の値を返す
$user = tap(User::find(1), function ($user) {
    $user->update(['last_login' => now()]);
});
// $user は User インスタンス

// コールバックなしの場合は HigherOrderTapProxy を返す
$user = tap($user)->update(['name' => 'New Name']);
```

#### retry()

```php
// 3回リトライ、100ms間隔
$result = retry(3, function ($attempts) {
    return Http::get('https://api.example.com');
}, 100);

// バックオフ配列指定
$result = retry([100, 200, 300], function () {
    // 1回目失敗後100ms、2回目失敗後200ms、3回目失敗後300ms
});

// 条件付きリトライ
$result = retry(3, function () {
    throw new Exception('Error');
}, 100, fn ($e) => $e instanceof RetryableException);
```

#### once()

```php
class Service {
    public function getValue() {
        return once(function () {
            // 重い計算（一度だけ実行される）
            return $this->expensiveCalculation();
        });
    }
}
```

### 2.3 ビジネスルール

1. **グローバル関数定義**
   - `function_exists()` でガードし、重複定義を防止
   - Composer オートロード経由で自動読み込み

2. **null安全性**
   - `optional()` は null を安全に扱う
   - `blank()` / `filled()` は null を適切に判定

3. **リトライロジック**
   - 失敗時は指定ミリ秒待機
   - 条件付きリトライ可能
   - バックオフ配列対応

## 3. 入出力仕様

### 3.1 入力

| 項目 | 型 | 説明 |
|-----|-----|------|
| value | `mixed` | 操作対象の値 |
| callback | `Closure` | 変換・処理用コールバック |

### 3.2 出力

| 項目 | 型 | 説明 |
|-----|-----|------|
| result | `mixed` | 処理結果 |

## 4. 依存関係

### 4.1 内部依存

| パッケージ | 用途 |
|-----------|------|
| Illuminate\Support\Arr | 配列操作 |
| Illuminate\Support\Env | 環境変数取得 |
| Illuminate\Support\Fluent | Fluent オブジェクト |
| Illuminate\Support\Optional | Optional オブジェクト |
| Illuminate\Support\Sleep | スリープ処理 |
| Illuminate\Support\Once | once() キャッシュ |

### 4.2 外部依存

| パッケージ | 用途 |
|-----------|------|
| なし | 外部依存なし |

## 5. エラー処理

| エラー種別 | 発生条件 | 処理内容 |
|-----------|---------|---------|
| RuntimeException | throw_if/throw_unless で条件成立 | 指定例外スロー |
| Throwable | retry() でリトライ上限超過 | 最後の例外をスロー |

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

### 6.1 推奨読解順序

1. **ファイル構造** (`Support/helpers.php`)
   - **17-37行目**: `append_config()` - 設定配列追加
   - **39-77行目**: `blank()` - 空判定（複数の型を考慮）
   - **79-91行目**: `class_basename()` - クラス名取得
   - **93-114行目**: `class_uses_recursive()` - 再帰トレイト取得
   - **116-139行目**: `e()` - HTMLエスケープ（DeferringDisplayableValue対応）
   - **141-153行目**: `env()` - 環境変数取得

2. **値判定・変換**
   - **155-169行目**: `filled()` - blank() の逆
   - **171-181行目**: `fluent()` - Fluent作成
   - **183-197行目**: `literal()` - リテラルオブジェクト

3. **オブジェクト操作**
   - **199-226行目**: `object_get()` - ドット記法アクセス
   - **239-257行目**: `once()` - 実行結果キャッシュ
   - **259-278行目**: `optional()` - null許容ラッパー

4. **リトライ処理**
   - **296-342行目**: `retry()` - リトライロジック

5. **文字列操作**
   - **344-370行目**: `str()` - Stringable取得

6. **タップ・変換**
   - **372-392行目**: `tap()` - タップパターン
   - **471-496行目**: `transform()` - 条件付き変換
   - **508-523行目**: `with()` - オプション変換

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

```
blank($value)
├── is_null($value) -> true
├── is_string($value) -> trim() === ''
├── is_numeric($value) || is_bool($value) -> false
├── $value instanceof Model -> false
├── $value instanceof Countable -> count() === 0
├── $value instanceof Stringable -> trim((string)$value) === ''
└── empty($value) -> fallback

retry($times, $callback, $sleep, $when)
└── loop:
    ├── try: $callback($attempts) -> return
    └── catch:
        ├── $times < 1 || !$when($e) -> throw
        └── Sleep::usleep() -> goto loop

once($callback)
└── Onceable::tryFromTrace()
    └── Once::instance()->value($onceable)
        └── cache hit -> return cached
        └── cache miss -> call_user_func($callback)
```

### 6.3 データフロー図

```
[入力値]
    |
    v
[ヘルパー関数]
    |
    +-- blank()/filled() --> bool判定
    +-- tap() --> 値をコールバックに渡し、値を返す
    +-- transform() --> 値が空でなければ変換
    +-- retry() --> 成功するまでリトライ
    +-- once() --> キャッシュから取得または実行
    |
    v
[結果]
```

### 6.4 読解のコツ

- **function_exists() ガード**: 各関数は重複定義を防ぐガード付き
- **型判定の順序**: `blank()` では特定の型から順に判定（Model > Countable > Stringable）
- **goto 文**: `retry()` は `goto` を使用した効率的なループ実装
- **静的キャッシュ**: `once()` は `Once` クラスで結果をキャッシュ

### 6.5 関連ファイル一覧

| ファイルパス | 種別 | 役割 |
|------------|------|------|
| `src/Illuminate/Support/helpers.php` | Helper | メインヘルパーファイル |
| `src/Illuminate/Support/Env.php` | Class | 環境変数アクセス |
| `src/Illuminate/Support/Fluent.php` | Class | Fluent オブジェクト |
| `src/Illuminate/Support/Optional.php` | Class | Optional ラッパー |
| `src/Illuminate/Support/Once.php` | Class | once() キャッシュ |
| `src/Illuminate/Support/Onceable.php` | Class | once() 用キー生成 |
| `src/Illuminate/Support/Sleep.php` | Class | スリープ処理 |
| `src/Illuminate/Support/HigherOrderTapProxy.php` | Class | tap() プロキシ |

## 7. 使用例

```php
// 値判定
if (filled($request->input('name'))) {
    // 名前が入力されている
}

// HTMLエスケープ
$safe = e($userInput);

// タップパターン
$user = tap(new User, function ($user) {
    $user->name = 'John';
    $user->save();
});

// null許容アクセス
$name = optional($user)->name; // $user が null でもエラーにならない

// リトライ
$response = retry(3, fn () => Http::get($url), 100);

// 条件付き例外
throw_if($user->isBlocked(), AuthorizationException::class);
throw_unless($user->hasPermission('edit'), AuthorizationException::class);

// 一度だけ実行
$config = once(fn () => $this->loadExpensiveConfig());

// 環境変数
$debug = env('APP_DEBUG', false);

// 条件付き変換
$upper = transform($name, fn ($n) => strtoupper($n), 'DEFAULT');
```

## 8. 改版履歴

| バージョン | 日付 | 変更内容 |
|-----------|------|---------|
| 1.0.0 | - | 初版作成 |
