Eloquent ORM이란
Laravel에는 Eloquent라는 객체 관계 매퍼(ORM)가 포함되어 있습니다.
Eloquent는 데이터베이스와의 대화를 쉽게 하기 위한 것으로, ActiveRecord 패턴 을 구현하고 있습니다.
Eloquent를 사용하면 데이터베이스의 각 테이블에 대응하는 “모델” 클래스를 준비합니다.
모델을 통해 레코드의 조회·삽입·갱신·삭제를 할 수 있습니다.
Eloquent를 사용하기 전에 config/database.php에서 데이터베이스 접속을 설정해 주세요.
기본적으로 .env 파일의 DB_* 설정이 사용됩니다.
모델 생성
make:model Artisan 명령으로 새 모델을 생성합니다.
php artisan make:model Post
마이그레이션과 동시에 생성하는 경우에는 -m 옵션을 사용합니다.
php artisan make:model Post -m
모델은 app/Models 디렉터리에 생성됩니다.
<? php
namespace App\Models ;
use Illuminate\Database\Eloquent\ Model ;
class Post extends Model
{
// ...
}
모델과 테이블의 대응 관계
Eloquent는 클래스명에서 테이블명을 자동으로 추측합니다.
클래스명을 스네이크케이스의 복수형으로 변환한 것이 테이블명이 됩니다.
모델명 테이블명 PostpostsUserusersAirTrafficControllerair_traffic_controllers
테이블명이 명명 규칙에 맞지 않는 경우, 모델에 $table 프로퍼티를 정의해 명시적으로 지정할 수 있습니다.
class Post extends Model
{
protected $table = 'blog_posts' ;
}
타임스탬프
Eloquent는 기본적으로 created_at과 updated_at 컬럼을 자동 관리합니다.
마이그레이션에서 $table->timestamps()를 추가해 두면 모델의 저장·갱신 시에 자동으로 값이 설정됩니다.
타임스탬프의 자동 관리를 무효화하려면 $timestamps를 false로 설정합니다.
class Post extends Model
{
public $timestamps = false ;
}
매스 어사인먼트 보호
Eloquent로 데이터를 일괄 저장할 때는 매스 어사인먼트 보호 설정이 필요합니다.
fillable
대입을 허용하는 컬럼을 $fillable 프로퍼티로 지정합니다.
class Post extends Model
{
protected $fillable = [
'user_id' ,
'title' ,
'body' ,
'published' ,
];
}
guarded
반대로 대입을 금지하는 컬럼을 지정하려면 $guarded를 사용합니다.
class Post extends Model
{
// 기본 키만 보호하고 나머지는 모두 허용한다
protected $guarded = [ 'id' ];
}
$guarded를 빈 배열로 하면 모든 컬럼에 대한 대입을 허용합니다.
사용자 입력을 그대로 전달하는 경우 의도하지 않은 컬럼이 변경될 위험이 있으므로, $fillable로 허용할 컬럼을 명시적으로 지정할 것을 권장합니다.
Eloquent 쿼리 실행 플로우
User::where()->get() 같은 쿼리가 어떻게 실행되는지, 내부 흐름을 보여 줍니다.
기본 CRUD 조작
레코드 가져오기(Read)
모든 레코드를 가져옵니다.
use App\Models\ Post ;
$posts = Post :: all ();
조건을 지정해서 가져옵니다.
// published가 true인 게시물을 가져오기
$publishedPosts = Post :: where ( 'published' , true ) -> get ();
// 첫 번째 1건만 가져오기
$post = Post :: where ( 'published' , true ) -> first ();
// ID로 1건 가져오기
$post = Post :: find ( 1 );
// 찾지 못하면 404 응답을 반환
$post = Post :: findOrFail ( 1 );
레코드 생성(Create)
create 메서드로 레코드를 하나 삽입합니다($fillable 설정이 필요합니다).
$post = Post :: create ([
'title' => '첫 게시물' ,
'body' => 'Laravel은 훌륭한 프레임워크입니다.' ,
'published' => true ,
]);
인스턴스를 생성해 개별적으로 대입할 수도 있습니다.
$post = new Post ;
$post -> title = '첫 게시물' ;
$post -> body = 'Laravel은 훌륭한 프레임워크입니다.' ;
$post -> save ();
레코드 갱신(Update)
모델을 가져와 값을 변경한 후 save를 호출하면 갱신됩니다.
$post = Post :: find ( 1 );
$post -> title = '갱신된 제목' ;
$post -> save ();
update 메서드를 사용하면 여러 컬럼을 한 번에 갱신할 수 있습니다.
Post :: find ( 1 ) -> update ([
'title' => '갱신된 제목' ,
'published' => true ,
]);
조건에 일치하는 여러 레코드를 일괄 갱신할 수도 있습니다.
Post :: where ( 'published' , false ) -> update ([ 'published' => true ]);
레코드 삭제(Delete)
delete 메서드로 레코드를 삭제합니다.
$post = Post :: find ( 1 );
$post -> delete ();
ID를 지정해 직접 삭제할 수도 있습니다.
Post :: destroy ( 1 );
// 여러 ID를 일괄 삭제
Post :: destroy ([ 1 , 2 , 3 ]);
기본 쿼리 메서드
메서드 설명 Post::all()모든 레코드를 가져오기 Post::find($id)ID로 1건 가져오기(찾지 못하면 null) Post::findOrFail($id)ID로 1건 가져오기(찾지 못하면 404) Post::where('column', 'value')->get()조건에 일치하는 레코드 가져오기 Post::where('column', 'value')->first()조건에 일치하는 첫 1건 가져오기 Post::where('column', 'value')->count()조건에 일치하는 건수 가져오기 Post::orderBy('created_at', 'desc')->get()정렬 순서를 지정해서 가져오기 Post::latest()->get()created_at 내림차순으로 가져오기Post::limit(10)->get()건수를 제한해서 가져오기
실전 예시: Post 모델을 사용한 데이터 조작
마이그레이션으로 생성한 posts 테이블을 조작하는 컨트롤러 예시입니다.
<? php
namespace App\Http\Controllers ;
use App\Models\ Post ;
use Illuminate\Http\ RedirectResponse ;
use Illuminate\Http\ Request ;
use Illuminate\View\ View ;
class PostController extends Controller
{
// 게시물 목록 표시
public function index () : View
{
$posts = Post :: where ( 'published' , true )
-> latest ()
-> get ();
return view ( 'posts.index' , [ 'posts' => $posts ]);
}
// 게시물 생성
public function store ( Request $request ) : RedirectResponse
{
$validated = $request -> validate ([
'title' => [ 'required' , 'string' , 'max:255' ],
'body' => [ 'required' , 'string' ],
'published' => [ 'boolean' ],
]);
Post :: create ([
... $validated ,
'user_id' => $request -> user () -> id ,
]);
return redirect ( '/posts' );
}
// 게시물 갱신
public function update ( Request $request , Post $post ) : RedirectResponse
{
$validated = $request -> validate ([
'title' => [ 'required' , 'string' , 'max:255' ],
'body' => [ 'required' , 'string' ],
]);
$post -> update ( $validated );
return redirect ( '/posts' );
}
// 게시물 삭제
public function destroy ( Post $post ) : RedirectResponse
{
$post -> delete ();
return redirect ( '/posts' );
}
}
컨트롤러 메서드의 인수에 Post $post라고 쓰면 Laravel이 라우트 파라미터에서 모델을 자동으로 가져옵니다(라우트 모델 바인딩).
Post::findOrFail($id)를 직접 작성할 필요가 없어집니다.
모델 이벤트의 라이프사이클
save()를 호출했을 때 발생하는 이벤트의 흐름을 보여줍니다. 신규 생성인지 갱신인지에 따라 다른 이벤트가 발생하지만, saving·saved는 양쪽 경우에 공통적으로 발생합니다.
다음 단계
마이그레이션 Eloquent가 이용하는 테이블을 마이그레이션으로 생성하는 방법을 되짚어 봅니다.