스코프란
Eloquent의 스코프는, 쿼리에 대한 제약을 정리하여 재이용할 수 있는 구조입니다. 스코프에는 2종류가 있습니다.로컬 스코프
정의
로컬 스코프는, 모델의 메서드에#[Scope] 어트리뷰트를 부여하여 정의합니다.
#[Scope] 어트리뷰트는 Illuminate\Database\Eloquent\Attributes 네임스페이스에 있습니다. PHP 8.0 이후의 네이티브 구문입니다.사용법
정의한 스코프는, 메서드로서 호출할 수 있습니다. 체인도 가능합니다.파라미터 전달
스코프 메서드의 제2인수 이후에 추가 파라미터를 정의할 수 있습니다.orWhere와의 조합
스코프를 orWhere로 연결할 때, 논리 그룹이 필요할 때가 있습니다.
글로벌 스코프
구조
글로벌 스코프는Illuminate\Database\Eloquent\Scope 인터페이스를 구현한 클래스입니다. 이 인터페이스는 apply 메서드 하나만을 요구합니다.
apply 메서드 안에서 쿼리 빌더에 제약을 추가합니다.
글로벌 스코프 클래스의 작성
make:scope 커맨드로 뼈대를 생성합니다.
app/Models/Scopes/ActiveScope.php가 생성됩니다.
모델에의 적용
1
#[ScopedBy] 어트리뷰트로 등록(권장)
Laravel 13에서는 여러 스코프를 배열로 지정할 수 있습니다.
#[ScopedBy] 어트리뷰트를 사용하는 것이 가장 심플합니다.2
booted() 메서드로 수동 등록
booted 메서드를 오버라이드하여 addGlobalScope를 호출하는 방법도 있습니다.User::all() 등 전 쿼리에 자동으로 WHERE is_active = 1이 붙습니다.
무명 클로저에 의한 글로벌 스코프
클래스를 별도 파일로 만들 정도는 아닌 단순한 스코프는, 클로저로 정의할 수 있습니다.글로벌 스코프의 제외
특정 쿼리에서는 스코프를 무효로 하고 싶은 장면이 있습니다.프레임워크 내부: SoftDeletingScope
Laravel 표준의SoftDeletes 트레이트가 글로벌 스코프를 어떻게 활용하고 있는지를 보면, 구현 패턴을 알 수 있습니다.
SoftDeletingScope는 Scope 인터페이스를 구현하고 있습니다.
withTrashed()의 구현을 본다
withTrashed()의 구현을 본다
withTrashed()는 실제로는 withoutGlobalScope($this)를 호출하고 있습니다. 즉 SoftDeletingScope 자신을 제외함으로써, 삭제된 레코드도 취득할 수 있게 하고 있습니다.onlyTrashed()도 마찬가지로, 스코프 자신을 제외한 뒤 whereNotNull('deleted_at')을 추가하고 있습니다.실전적인 유스케이스
멀티 테넌트: 테넌트 ID에 의한 자동 좁혀 넣기
SaaS 애플리케이션에서는, 전 쿼리에 테넌트 ID의 필터를 자동 적용하는 것이 중요합니다.Post::all()을 호출하는 것만으로, 인증 중인 사용자의 테넌트 데이터만이 반환됩니다.
공개/비공개 필터
관리 화면에서는 비공개 게시물도 표시하고 싶지만, 프론트엔드에서는 공개된 것만 표시하고 싶은 경우입니다.withoutGlobalScope로 스코프를 제외합니다.
select가 아닌 addSelect를 사용한다
다음 단계
Eloquent 커스텀 캐스트
속성의 변환 로직을 커스텀 캐스트로서 구현하고, Value Object 패턴을 활용하는 방법을 배웁니다.