본문으로 건너뛰기
버전: 9.x

Eloquent: Serialization

Introduction​

Laravel을 사용해 API를 개발할 때, 모델과 연관관계를 배열 또는 JSON 형태로 변환해야 하는 경우가 많습니다. Eloquent는 이러한 변환을 쉽게 할 수 있는 편리한 메서드들을 제공하며, 모델의 직렬화 결과에 포함될 속성을 세밀하게 제어할 수 있는 기능도 지원합니다.

Eloquent 모델과 컬렉션의 JSON 직렬화를 더 강력하게 다루고 싶다면 Eloquent API resources 문서를 참고하시기 바랍니다.

Serializing Models & Collections​

Serializing To Arrays​

모델과 함께 로드된 relationships를 배열로 변환하려면 toArray 메서드를 사용합니다. 이 메서드는 재귀적으로 동작하기 때문에, 모든 속성과 연관관계(연관관계의 또 다른 연관관계까지 포함)까지 전부 배열로 변환됩니다.

use App\Models\User;

$user = User::with('roles')->first();

return $user->toArray();

attributesToArray 메서드는 모델의 속성만 배열로 변환하며, 연관관계는 포함하지 않습니다.

$user = User::first();

return $user->attributesToArray();

또한, 모델의 전체 collections을 컬렉션 인스턴스에서 toArray 메서드를 호출하여 배열로 변환할 수도 있습니다.

$users = User::all();

return $users->toArray();

Serializing To JSON​

모델을 JSON으로 변환하려면 toJson 메서드를 사용합니다. toArray와 마찬가지로, toJson 역시 재귀적으로 모든 속성과 연관관계를 JSON으로 변환합니다. 또한 supported by PHP에 나열된 어떠한 JSON 인코딩 옵션도 함께 지정할 수 있습니다.

use App\Models\User;

$user = User::find(1);

return $user->toJson();

return $user->toJson(JSON_PRETTY_PRINT);

또는, 모델이나 컬렉션을 문자열로 casting(cast)하면 toJson 메서드가 자동으로 호출되어 JSON 문자열이 반환됩니다.

return (string) User::find(1);

이처럼 모델이나 컬렉션이 문자열로 casting될 때 JSON으로 변환되므로, 애플리케이션의 라우트나 컨트롤러에서 Eloquent 객체를 직접 반환할 수 있습니다. Laravel은 라우트나 컨트롤러에서 반환된 Eloquent 모델 및 컬렉션을 자동으로 JSON으로 직렬화합니다.

Route::get('users', function () {
return User::all();
});

Relationships​

Eloquent 모델이 JSON으로 변환될 때, 로드된 연관관계는 JSON 객체의 속성으로 자동 포함됩니다. 또한 Eloquent 연관관계 메서드는 카멜케이스로 정의하지만, JSON의 속성명은 스네이크케이스로 변환되어 사용됩니다.

Hiding Attributes From JSON​

비밀번호처럼 모델의 배열 또는 JSON 표현에 포함하고 싶지 않은 속성이 있을 수 있습니다. 이럴 때는 모델에 $hidden 속성을 추가하면 됩니다. $hidden 속성에 명시된 배열의 내용은 모델이 직렬화될 때 포함되지 않습니다.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = ['password'];
}

연관관계를 숨기고 싶다면, 해당 연관관계의 메서드 이름을 Eloquent 모델의 $hidden 속성에 추가하면 됩니다.

또는, visible 속성을 사용하여 배열 및 JSON 표현에 포함될 속성만을 "허용 목록"으로 명시할 수도 있습니다. $visible 배열에 포함되지 않은 모든 속성은 배열이나 JSON 변환 시 숨겨집니다.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
/**
* The attributes that should be visible in arrays.
*
* @var array
*/
protected $visible = ['first_name', 'last_name'];
}

Temporarily Modifying Attribute Visibility​

일반적으로 숨겨진 속성을 일시적으로 보이게 하고 싶다면 makeVisible 메서드를 사용할 수 있습니다. makeVisible 메서드는 모델 인스턴스를 반환합니다.

return $user->makeVisible('attribute')->toArray();

반대로, 평소에 보이는 속성을 일시적으로 숨기고 싶다면 makeHidden 메서드를 사용할 수 있습니다.

return $user->makeHidden('attribute')->toArray();

모델의 visible 또는 hidden 속성 전체를 일시적으로 덮어쓰려면 각각 setVisible과 setHidden 메서드를 사용하세요.

return $user->setVisible(['id', 'name'])->toArray();

return $user->setHidden(['email', 'password', 'remember_token'])->toArray();

Appending Values To JSON​

모델을 배열이나 JSON으로 변환할 때, 데이터베이스 컬럼에 해당하지 않는 속성을 추가하고 싶을 때가 있습니다. 이럴 때는 먼저 해당 값에 대한 accessor를 정의합니다.

<?php

namespace App\Models;

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

class User extends Model
{
/**
* Determine if the user is an administrator.
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
protected function isAdmin(): Attribute
{
return new Attribute(
get: fn () => 'yes',
);
}
}

그리고 나서, 생성한 속성명을 모델의 appends 속성에 추가합니다. 일반적으로 속성명은 직렬화된 "스네이크케이스"로 명시해야 하며, accessor의 PHP 메서드는 카멜케이스로 정의하더라도 상관없습니다.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
/**
* The accessors to append to the model's array form.
*
* @var array
*/
protected $appends = ['is_admin'];
}

이렇게 appends 목록에 속성을 추가하면, 그 속성이 모델의 배열 및 JSON 표현에 함께 포함됩니다. appends 배열의 속성도 모델에 설정된 visible 또는 hidden 옵션을 함께 따릅니다.

Appending At Run Time​

실행 중에 모델 인스턴스에서 추가로 속성을 붙이고 싶을 때는 append 메서드를 사용할 수 있습니다. 또는, setAppends 메서드를 통해 해당 모델 인스턴스의 추가 속성 목록 전체를 덮어쓸 수도 있습니다.

return $user->append('is_admin')->toArray();

return $user->setAppends(['is_admin'])->toArray();

Date Serialization​

Customizing The Default Date Format​

기본 날짜 직렬화 포맷을 변경하고 싶다면 serializeDate 메서드를 오버라이드하면 됩니다. 이 메서드는 데이터베이스에 저장되는 날짜 포맷에는 영향을 주지 않습니다.

/**
* Prepare a date for array / JSON serialization.
*
* @param \DateTimeInterface $date
* @return string
*/
protected function serializeDate(DateTimeInterface $date)
{
return $date->format('Y-m-d');
}

Customizing The Date Format Per Attribute​

특정 Eloquent 날짜 속성만 직렬화 포맷을 다르게 지정하고 싶다면, 모델의 cast declarations에서 날짜 포맷을 지정할 수 있습니다.

protected $casts = [
'birthday' => 'date:Y-m-d',
'joined_at' => 'datetime:Y-m-d H:00',
];