1 개요[ | ]
- Eloquent: Serialization
- 엘로퀀트: 직렬화
2 소개[ | ]
Laravel로 API를 구축할 때 모델과 관계를 배열이나 JSON으로 변환해야 하는 경우가 많습니다. Eloquent에는 이러한 변환을 위한 편리한 메소드가 포함되어 있으며, 모델의 직렬화된 표현에 포함되는 속성을 제어할 수도 있습니다.
Eloquent 모델 및 컬렉션 JSON 직렬화를 더욱 강력하게 처리하는 방법을 알아보려면, Eloquent API 리소스에 대한 문서를 확인하세요.
3 모델과 콜렉션 직렬화[ | ]
3.1 배열로 직렬화[ | ]
모델과 로드된 관계를 배열로 변환하려면 toArray
메소드를 사용해야 합니다. 이 메소드는 재귀적이므로 모든 속성과 모든 관계(관계의 관계 포함)가 배열로 변환됩니다:
use App\Models\User;
$user = User::with('roles')->first();
return $user->toArray();
attributesToArray
메소드는 모델의 속성을 배열로 변환할 수 있지만, 관계는 변환하지 않습니다:
$user = User::first();
return $user->attributesToArray();
모델의 콜렉션 전체를 배열로 변환하려면 콜렉션 인스턴스에서 toArray
메소드를 호출할 수 있습니다:
$users = User::all();
return $users->toArray();
3.2 JSON으로 직렬화[ | ]
모델을 JSON으로 변환하려면 toJson
메소드를 사용해야 합니다. toArray
메소드와 마찬가지로 toJson
메소드도 재귀적으로 동작하여 모든 속성과 관계가 JSON으로 변환됩니다. 또한 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 객체를 직접 반환할 수 있습니다. 라라벨은 라우트나 컨트롤러에서 반환된 Eloquent 모델과 컬렉션을 자동으로 JSON으로 직렬화합니다:
Route::get('users', function () {
return User::all();
});
- 관계
Eloquent 모델이 JSON으로 변환될 때, 로드된 관계도 JSON 객체의 속성으로 자동으로 포함됩니다. 또한, Eloquent 관계 메소드는 "camel case" 메서드 이름으로 정의되지만, 관계의 JSON 속성은 "snake case"로 표시됩니다.
4 JSON에서 속성 숨기기[ | ]
때로는 패스워드와 같은 속성을 모델의 배열 또는 JSON 표현에 포함하지 않도록 제한하고 싶을 때가 있습니다. 이를 위해 모델에 $hidden
속성을 추가하세요. $hidden
속성 배열에 나열된 속성은 모델의 직렬화된 표현에 포함되지 않습니다:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 배열에 포함되지 않아야 하는 속성들.
*
* @var array
*/
protected $hidden = ['password'];
}
관계(relationships)를 숨기려면 관계 메소드 이름을 Eloquent 모델의 $hidden
속성에 추가하세요.
반대로, visible
속성을 사용하여 모델의 배열 및 JSON 표현에 포함해야 하는 속성의 "허용 목록"을 정의할 수 있습니다. $visible
배열에 없는 모든 속성은 모델이 배열 또는 JSON으로 변환될 때 숨겨집니다:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 배열에 포함되어야 하는 속성들.
*
* @var array
*/
protected $visible = ['first_name', 'last_name'];
}
- 속성 가시성 임시 변경
일반적으로 숨겨진 속성을 특정 모델 인스턴스에서 보이도록 하고 싶다면 makeVisible
메소드를 사용할 수 있습니다. makeVisible
메소드는 모델 인스턴스를 반환합니다:
return $user->makeVisible('attribute')->toArray();
마찬가지로, 일반적으로 보이는 속성을 숨기고 싶다면 makeHidden
메소드를 사용할 수 있습니다:
return $user->makeHidden('attribute')->toArray();
모든 가시 또는 숨김 속성을 임시로 재정의하려면 setVisible
및 setHidden
메소드를 각각 사용할 수 있습니다:
return $user->setVisible(['id', 'name'])->toArray();
return $user->setHidden(['email', 'password', 'remember_token'])->toArray();
5 JSON에 값 덧붙이기[ | ]
때때로 모델을 배열이나 JSON으로 변환할 때 데이터베이스에 해당하는 열이 없는 속성을 추가하고 싶을 수 있습니다. 이를 위해 먼저 값에 대한 접근자를 정의해야 합니다:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 사용자가 관리자인지 확인합니다.
*/
protected function isAdmin(): Attribute
{
return new Attribute(
get: fn () => 'yes',
);
}
}
접근자가 모델의 배열 및 JSON 표현에 항상 추가되도록 하려면 모델의 appends
속성에 속성 이름을 추가할 수 있습니다. 접근자의 PHP 메소드는 "camel case"로 정의되었지만 속성 이름은 "snake case" 직렬화 표현을 사용하여 참조된다는 점에 유의하세요:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 모델의 배열 형식에 추가할 접근자들.
*
* @var array
*/
protected $appends = ['is_admin'];
}
속성이 appends
목록에 추가되면 모델의 배열 및 JSON 표현에 포함됩니다. appends
배열의 속성은 모델에 설정된 visible
및 hidden
설정도 따릅니다.
- 런타임에 추가하기
런타임에, 추가 속성을 모델 인스턴스에 추가하려면 append
메소드를 사용할 수 있습니다. 또는 setAppends
메소드를 사용하여 특정 모델 인스턴스에 대한 전체 추가 속성 배열을 재정의할 수 있습니다:
return $user->append('is_admin')->toArray();
return $user->setAppends(['is_admin'])->toArray();
6 날짜 직렬화[ | ]
- 기본 날짜 형식 커스터마이징
기본 직렬화 형식을 커스터마이징하려면 serializeDate
메소드를 재정의하면 됩니다. 이 메소드는 날짜가 데이터베이스에 저장되는 형식에는 영향을 미치지 않습니다:
/**
* 배열 / JSON 직렬화를 위한 날짜 준비.
*/
protected function serializeDate(DateTimeInterface $date): string
{
return $date->format('Y-m-d');
}
- 속성별 날짜 형식 커스터마이징
Eloquent 날짜 속성의 직렬화 형식을 개별적으로 커스터마이징하려면 모델의 cast 선언에서 날짜 형식을 지정할 수 있습니다:
protected function casts(): array
{
return [
'birthday' => 'date:Y-m-d',
'joined_at' => 'datetime:Y-m-d H:00',
];
}