Support Contracts란
Illuminate\Contracts\Support에는 Laravel 전반에서 사용되는 작지만 중요한 인터페이스가 모여 있습니다.
특히 Arrayable / Jsonable / Htmlable / Responsable은, Value Object·DTO·응답 오브젝트를 Laravel의 기존 흐름에 자연스럽게 태우기 위한 기본 패턴입니다.
여기에서 다루는 시그니처는 Laravel 13.x의 공식 소스(laravel/framework)를 참조하고 있습니다.
1) Arrayable
인터페이스 정의
interface Arrayable
{
public function toArray ();
}
구현 예
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
인터페이스 정의
interface Jsonable
{
public function toJson ( $options = 0 );
}
구현 예
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
인터페이스 정의
interface Htmlable
{
public function toHtml ();
}
구현 예
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 !!}를 사용하는 상황에서도, 출력을 오브젝트로 관리하기 쉬움
Htmlable을 구현하는 클래스 내에서는, 사용자 입력을 그대로 연결하지 말고, 필요한 값은 e()로 이스케이프한 뒤 삽입해 주세요.
4) Responsable
인터페이스 정의
interface Responsable
{
public function toResponse ( $request );
}
구현 예
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 표현과 도메인 표현을 분리하기 쉬워짐
구현의 구분 사용 가이드
데이터를 배열화하여 재이용하고 싶다
Arrayable을 구현하고, toArray()에 정규화 로직을 집약합니다.
JSON 표현을 제어하고 싶다
Jsonable을 구현하고, toJson($options)에서 출력 형식을 명시합니다.
HTML 조각으로 다루고 싶다
Htmlable을 구현하고, toHtml()에서 렌더링 문자열을 반환합니다.
HTTP 응답을 직접 반환하고 싶다
Responsable을 구현하고, toResponse($request)로 책무를 집약합니다.
다음으로 읽을 페이지
Macroable 트레이트 기존 클래스에 고유 메서드를 추가하는 확장 패턴을 배웁니다.
Conditionable 트레이트 when() / unless()로 조건 분기를 넣는 설계를 배웁니다.
tap() 헬퍼 / Tappable 부수 효과를 끼워 넣으며 값을 반환하는 체인 설계를 배웁니다.
Dumpable 트레이트 dump() / dd()를 오브젝트에 삽입하는 디버그 기법을 배웁니다.