Eloquent: Serialization
- Introduction
- Serializing Models & Collections
- Hiding Attributes From JSON
- Appending Values To JSON
- Date 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);
또는, 모델이나 컬렉션을 문자열로 형변환하면 자동으로 해당 객체의 toJson 메서드가 호출됩니다.
return (string) User::find(1);
모델이나 컬렉션을 문자열로 변환할 때 자동으로 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'];
}
연관관계를 숨기고 싶다면,
$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();
Appending Values To JSON
모델을 배열 또는 JSON으로 변환할 때, 데이터베이스 컬럼에는 존재하지 않는 속성을 추가하고 싶을 때가 있습니다. 이 경우, 먼저 해당 값을 위한 accessor를 정의하십시오.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Determine if the user is an administrator.
*
* @return bool
*/
public function getIsAdminAttribute()
{
return $this->attributes['admin'] === 'yes';
}
}
accessor를 만들었다면, 모델의 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',
];