메인 콘텐츠로 건너뛰기

시작하기

액세서, 뮤테이터, 속성 캐스트는 Eloquent 모델의 속성값을 모델 인스턴스에서 취득·설정할 때 변환하는 구조입니다.
  • 액세서 — DB에서 취득한 원시 값을 가공해 애플리케이션에 전달
  • 뮤테이터 — 애플리케이션에서 세팅된 값을 가공해 DB에 저장
  • 캐스트 — 추가 메서드 없이 속성의 타입 변환을 선언적으로 정의

액세서 정의

액세서를 정의하려면 모델에 protected 메서드를 추가합니다. 메서드 이름은 카멜케이스, 반환값 타입은 Illuminate\Database\Eloquent\Casts\Attribute로 합니다.
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 사용자의 퍼스트 네임을 취득합니다.
     */
    protected function firstName(): Attribute
    {
        return Attribute::make(
            get: fn (string $value) => ucfirst($value),
        );
    }
}
get 클로저에 DB의 원시 값이 전달됩니다. 모델 인스턴스에서 first_name 프로퍼티로 접근할 수 있습니다.
$user = User::find(1);

$firstName = $user->first_name; // ucfirst() 가 적용된 값
액세서로 계산한 값을 JSON/배열에 포함시키고 싶은 경우, 모델의 $appends 프로퍼티에 스네이크 케이스로 추가해 주십시오.

여러 속성으로부터 값 객체를 생성

get 클로저는 두 번째 인수로 $attributes(모델의 모든 속성)를 받을 수 있습니다. 여러 컬럼을 조합해 하나의 값 객체를 반환할 수 있습니다.
use App\Support\Address;
use Illuminate\Database\Eloquent\Casts\Attribute;

protected function address(): Attribute
{
    return Attribute::make(
        get: fn (mixed $value, array $attributes) => new Address(
            $attributes['address_line_one'],
            $attributes['address_line_two'],
        ),
    );
}

액세서 캐시

값 객체를 반환하는 액세서는 Eloquent가 같은 인스턴스를 반환하도록 자동으로 캐시합니다. 문자열이나 숫자 등 기본 타입에서도 캐시하고 싶은 경우 shouldCache()를 호출합니다.
protected function hash(): Attribute
{
    return Attribute::make(
        get: fn (string $value) => bcrypt(gzuncompress($value)),
    )->shouldCache();
}
객체의 캐시를 무효로 하고 싶은 경우 withoutObjectCaching()을 사용합니다.
protected function address(): Attribute
{
    return Attribute::make(
        get: fn (mixed $value, array $attributes) => new Address(
            $attributes['address_line_one'],
            $attributes['address_line_two'],
        ),
    )->withoutObjectCaching();
}

뮤테이터 정의

뮤테이터는 Attribute::make()set 인수로 정의합니다. 액세서와 같은 메서드에 함께 정리할 수 있습니다.
protected function firstName(): Attribute
{
    return Attribute::make(
        get: fn (string $value) => ucfirst($value),
        set: fn (string $value) => strtolower($value),
    );
}
모델에 값을 세팅하면 set 클로저가 호출됩니다.
$user = User::find(1);
$user->first_name = 'SALLY'; // strtolower() 가 적용되어 'sally' 가 저장됨

여러 속성에 쓰기

set 클로저에서 배열을 반환하면, 여러 컬럼을 함께 업데이트할 수 있습니다.
use App\Support\Address;
use Illuminate\Database\Eloquent\Casts\Attribute;

protected function address(): Attribute
{
    return Attribute::make(
        get: fn (mixed $value, array $attributes) => new Address(
            $attributes['address_line_one'],
            $attributes['address_line_two'],
        ),
        set: fn (Address $value) => [
            'address_line_one' => $value->lineOne,
            'address_line_two' => $value->lineTwo,
        ],
    );
}

속성 캐스트

캐스트는 액세서·뮤테이터를 쓰지 않아도 속성의 타입 변환을 선언할 수 있는 간편한 방법입니다. 모델의 casts() 메서드에서 배열을 반환합니다.
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected function casts(): array
    {
        return [
            'is_admin'   => 'boolean',
            'score'      => 'float',
            'settings'   => 'array',
            'created_at' => 'datetime',
        ];
    }
}

내장 캐스트 목록

캐스트설명
integer / int정수
float / double / real부동소수점 수
decimal:<자릿수>지정 자릿수의 소수
string문자열
boolean / bool진위값(0/1 포함)
arrayJSON을 배열로 상호 변환
objectJSON을 객체로 상호 변환
collectionJSON을 컬렉션으로 변환
date날짜(Carbon)
datetime일시(Carbon)
immutable_date불변 날짜
immutable_datetime불변 일시
timestampUNIX 타임스탬프
hashed저장 시에 해시화
encrypted저장 시에 암호화
null 속성은 캐스트되지 않습니다. 또한 릴레이션 이름과 같은 이름의 캐스트나, 주 키에의 캐스트는 정의하지 마십시오.

Stringable 캐스트

AsStringable을 사용하면 속성을 Illuminate\Support\Stringable 객체로 다룰 수 있습니다.
use Illuminate\Database\Eloquent\Casts\AsStringable;

protected function casts(): array
{
    return [
        'bio' => AsStringable::class,
    ];
}

배열·JSON 캐스트

JSON/TEXT 컬럼을 PHP 배열로 투과적으로 다룰 수 있습니다.
protected function casts(): array
{
    return [
        'options' => 'array',
    ];
}
$user = User::find(1);

// 자동으로 PHP 배열로 취득
$options = $user->options;

// 변경해서 저장하면 자동으로 JSON 직렬화됨
$user->options = array_merge($options, ['theme' => 'dark']);
$user->save();
-> 연산자로 JSON의 특정 키만 업데이트할 수도 있습니다.
$user->update(['options->theme' => 'dark']);

AsArrayObject / AsCollection 캐스트

표준 array 캐스트는 배열의 특정 오프셋을 직접 변경하려고 하면 오류가 발생합니다. AsArrayObjectAsCollection을 사용하면 이 문제를 회피할 수 있습니다.
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Casts\AsCollection;

protected function casts(): array
{
    return [
        'options' => AsArrayObject::class,   // ArrayObject 로 다룸
        'tags'    => AsCollection::class,    // Collection 으로 다룸
    ];
}
커스텀 컬렉션 클래스를 사용하고 싶은 경우 using()을 지정합니다.
use App\Collections\TagCollection;
use Illuminate\Database\Eloquent\Casts\AsCollection;

protected function casts(): array
{
    return [
        'tags' => AsCollection::using(TagCollection::class),
    ];
}

일시 캐스트

created_at / updated_at은 기본적으로 Carbon으로 캐스트됩니다. 추가의 일시 컬럼도 동일하게 정의할 수 있습니다.
protected function casts(): array
{
    return [
        'published_at' => 'datetime',
        'expires_at'   => 'immutable_datetime',
    ];
}
포맷을 지정하면 JSON 직렬화 시에 그 포맷이 사용됩니다.
protected function casts(): array
{
    return [
        'published_at' => 'datetime:Y-m-d',
    ];
}
모든 날짜의 기본 직렬화 포맷을 바꾸고 싶은 경우 serializeDate()를 오버라이드합니다(DB 저장 포맷에는 영향을 주지 않습니다).
use DateTimeInterface;

protected function serializeDate(DateTimeInterface $date): string
{
    return $date->format('Y-m-d');
}
immutable_datetime을 사용하면 Carbon 대신 CarbonImmutable이 반환됩니다. 원래 인스턴스를 변경하지 않고 일시 조작을 할 수 있어 부작용이 없는 코드를 쓰기 쉬워집니다.

Enum 캐스트

PHP 8.1 이후의 Backed Enum을 캐스트로 지정할 수 있습니다.
<?php

namespace App\Enums;

enum ServerStatus: string
{
    case Provisioned = 'provisioned';
    case Ready       = 'ready';
    case Archived    = 'archived';
}
use App\Enums\ServerStatus;

protected function casts(): array
{
    return [
        'status' => ServerStatus::class,
    ];
}
DB에는 Enum의 백킹 값(string 또는 int)이 저장되고, 취득 시에는 Enum 인스턴스로 변환됩니다.
$server = Server::find(1);

if ($server->status === ServerStatus::Provisioned) {
    $server->status = ServerStatus::Ready;
    $server->save();
}

Enum 의 배열 캐스트

여러 Enum 값을 1개의 컬럼에 배열로 저장하고 싶은 경우 AsEnumCollection을 사용합니다.
use App\Enums\ServerStatus;
use Illuminate\Database\Eloquent\Casts\AsEnumCollection;

protected function casts(): array
{
    return [
        'statuses' => AsEnumCollection::of(ServerStatus::class),
    ];
}

쿼리 시의 캐스트

쿼리 실행 시에 동적으로 캐스트를 적용하려면 withCasts()를 사용합니다.
use App\Models\Post;
use App\Models\User;

$users = User::select([
    'users.*',
    'last_posted_at' => Post::selectRaw('MAX(created_at)')
        ->whereColumn('user_id', 'users.id'),
])->withCasts([
    'last_posted_at' => 'datetime',
])->get();

커스텀 캐스트

독자적인 캐스트 클래스를 작성할 수도 있습니다. CastsAttributes 인터페이스를 구현하고 getset 메서드를 정의합니다.
php artisan make:cast AsJson
상세한 구현 방법(Value Object 패턴, 인바운드 캐스트, Castables 등)은 다음의 상급 페이지를 참조하십시오.

커스텀 캐스트 상세 설명

CastsAttributes 인터페이스의 구현 방법이나, Value Object 패턴·Castables 등 상급의 커스텀 캐스트를 설명합니다.

관련 페이지

Eloquent API 리소스

모델을 일관된 JSON API 응답으로 변환하는 리소스 클래스의 사용법을 확인합니다.
마지막 수정일 2026년 7월 13일