> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Support Contracts (Arrayable / Jsonable / Htmlable / Responsable)

> Illuminate\Contracts\Support의 주요 컨트랙트 4종을, Laravel 13의 공식 소스 코드에 기반하여 해설합니다.

## Support Contracts란

`Illuminate\Contracts\Support`에는 Laravel 전반에서 사용되는 작지만 중요한 인터페이스가 모여 있습니다.\
특히 `Arrayable` / `Jsonable` / `Htmlable` / `Responsable`은, Value Object·DTO·응답 오브젝트를 Laravel의 기존 흐름에 자연스럽게 태우기 위한 기본 패턴입니다.

```mermaid theme={null}
flowchart TD
    A["Value Object / DTO"] --> B["Arrayable<br>toArray()"]
    A --> C["Jsonable<br>toJson($options = 0)"]
    A --> D["Htmlable<br>toHtml()"]
    A --> E["Responsable<br>toResponse($request)"]
    B --> F["JsonResponse / Eloquent / Collection"]
    C --> F
    D --> G["e() helper / Blade output"]
    E --> H["Controller return / Router::toResponse()"]
```

<Info>
  여기에서 다루는 시그니처는 Laravel 13.x의 공식 소스(`laravel/framework`)를 참조하고 있습니다.
</Info>

## 1) Arrayable

### 인터페이스 정의

```php theme={null}
interface Arrayable
{
    public function toArray();
}
```

### 구현 예

```php theme={null}
use Illuminate\Contracts\Support\Arrayable;

final class Money implements Arrayable
{
    public function __construct(
        public readonly int $amount,
        public readonly string $currency,
    ) {}

    public function toArray(): array
    {
        return [
            'amount' => $this->amount,
            'currency' => $this->currency,
        ];
    }
}
```

### Laravel 코어에서의 사용 예

* `Illuminate\Database\Eloquent\Model`은 `Arrayable`을 구현하고, `toArray()`를 제공
* `Illuminate\Http\JsonResponse::setData()`는 `Arrayable`을 검출하면 `json_encode($data->toArray(), ...)`로 시리얼라이즈

### 패키지 개발에서의 활용 포인트

* DTO나 Value Object를 컨트롤러·리소스·로그 출력에서 공통 포맷화할 수 있음
* `array`로의 변환 책무를 오브젝트 측에 가둘 수 있음

## 2) Jsonable

### 인터페이스 정의

```php theme={null}
interface Jsonable
{
    public function toJson($options = 0);
}
```

### 구현 예

```php theme={null}
use Illuminate\Contracts\Support\Jsonable;

final class ApiPayload implements Jsonable
{
    public function __construct(
        private array $data,
    ) {}

    public function toJson($options = 0): string
    {
        return json_encode([
            'data' => $this->data,
            'generated_at' => now()->toIso8601String(),
        ], $options | JSON_THROW_ON_ERROR);
    }
}
```

### Laravel 코어에서의 사용 예

* `Model`은 `Jsonable`도 구현하고, `toJson($options = 0)`을 제공
* `JsonResponse::setData()`는 `Jsonable`을 최우선으로 판정하여 `toJson()`을 사용

### 패키지 개발에서의 활용 포인트

* 감사 로그·웹훅 송신 등에서 JSON 구조를 엄밀하게 고정할 수 있음
* `json_encode()` 측에 맡기지 않고, 도메인 사정의 JSON 표현을 명시할 수 있음

## 3) Htmlable

### 인터페이스 정의

```php theme={null}
interface Htmlable
{
    public function toHtml();
}
```

### 구현 예

```php theme={null}
use Illuminate\Contracts\Support\Htmlable;

final class BadgeHtml implements Htmlable
{
    public function __construct(
        private string $label,
    ) {}

    public function toHtml(): string
    {
        $escaped = e($this->label);

        return "<span class=\"badge\">{$escaped}</span>";
    }
}
```

### Laravel 코어에서의 사용 예

* `Illuminate\Support\HtmlString`은 `Htmlable`을 구현
* `e()` 헬퍼는 인수가 `Htmlable`인 경우 `toHtml()`을 반환(재이스케이프하지 않음)

### 패키지 개발에서의 활용 포인트

* Blade 내에서 안전하게 HTML 조각을 전달하는 책무 경계를 명확히 할 수 있음
* `{!! $obj !!}`를 사용하는 상황에서도, 출력을 오브젝트로 관리하기 쉬움

<Tip>
  `Htmlable`을 구현하는 클래스 내에서는, 사용자 입력을 그대로 연결하지 말고, 필요한 값은 `e()`로 이스케이프한 뒤 삽입해 주세요.
</Tip>

## 4) Responsable

### 인터페이스 정의

```php theme={null}
interface Responsable
{
    public function toResponse($request);
}
```

### 구현 예

```php theme={null}
use Illuminate\Contracts\Support\Responsable;

final class ExportCsvResponse implements Responsable
{
    public function __construct(
        private array $rows,
        private string $filename = 'export.csv',
    ) {}

    /**
     * @param \Illuminate\Http\Request $request
     */
    public function toResponse($request)
    {
        return response()->streamDownload(function () {
            $stream = fopen('php://output', 'w');

            foreach ($this->rows as $row) {
                fputcsv($stream, $row);
            }

            fclose($stream);
        }, $this->filename, [
            'Content-Type' => 'text/csv',
        ]);
    }
}
```

### Laravel 코어에서의 사용 예

* `Illuminate\Routing\Router::toResponse()`는 최초에 `Responsable`을 판정하고, `$response->toResponse($request)`를 호출
* `Illuminate\Http\Resources\Json\JsonResource`는 `Responsable`을 구현하고 있으며, 컨트롤러에서 직접 `return UserResource::make($user);`가 가능

### 패키지 개발에서의 활용 포인트

* 컨트롤러에서 배열 조립을 하지 않고, 응답 생성을 오브젝트로 위임할 수 있음
* "DTO를 그대로 return"하는 설계로 하기 쉬워지고, HTTP 표현과 도메인 표현을 분리하기 쉬워짐

## 구현의 구분 사용 가이드

<Steps>
  <Step title="데이터를 배열화하여 재이용하고 싶다">
    `Arrayable`을 구현하고, `toArray()`에 정규화 로직을 집약합니다.
  </Step>

  <Step title="JSON 표현을 제어하고 싶다">
    `Jsonable`을 구현하고, `toJson($options)`에서 출력 형식을 명시합니다.
  </Step>

  <Step title="HTML 조각으로 다루고 싶다">
    `Htmlable`을 구현하고, `toHtml()`에서 렌더링 문자열을 반환합니다.
  </Step>

  <Step title="HTTP 응답을 직접 반환하고 싶다">
    `Responsable`을 구현하고, `toResponse($request)`로 책무를 집약합니다.
  </Step>
</Steps>

## 다음으로 읽을 페이지

<Columns cols={2}>
  <Card title="Macroable 트레이트" icon="puzzle-piece" href="/ko/advanced/macroable">
    기존 클래스에 고유 메서드를 추가하는 확장 패턴을 배웁니다.
  </Card>

  <Card title="Conditionable 트레이트" icon="git-branch" href="/ko/advanced/conditionable">
    `when()` / `unless()`로 조건 분기를 넣는 설계를 배웁니다.
  </Card>

  <Card title="tap() 헬퍼 / Tappable" icon="hand-point-up" href="/ko/advanced/tap">
    부수 효과를 끼워 넣으며 값을 반환하는 체인 설계를 배웁니다.
  </Card>

  <Card title="Dumpable 트레이트" icon="bug" href="/ko/advanced/dumpable">
    `dump()` / `dd()`를 오브젝트에 삽입하는 디버그 기법을 배웁니다.
  </Card>
</Columns>


## Related topics

- [Contracts(계약)](/ko/contracts.md)
- [Laravel Boost](/ko/boost.md)
- [지연 서비스 프로바이더](/ko/advanced/deferred-provider.md)
- [헬퍼 함수](/ko/helpers.md)
- [AI SDK의 커스텀 프로바이더 만들기](/ko/advanced/ai-sdk-custom-provider.md)
