php
Laravel Query Builder의 join()의 on() 사용 시 주의점
실수한 내용
Laravel Query Builder를 사용하면서 아래와 같이 join() 뒤에 바로 on()을 체이닝하여 오류가 발생했다.
잘못된 예시
$query
->join('users')
->on('users.id', '=', 'posts.user_id');
원인 분석
메서드 체이닝 시에는 현재 반환되는 객체가 어떤 객체인지 이해하는 것이 중요하다.
join()을 호출하면 반환되는 것은 JoinClause 객체가 아니라 원래의 Query Builder 객체이다.
반면 on() 메서드는 Query Builder가 아니라 JoinClause 객체에 정의되어 있다.
따라서 아래와 같은 형태는 불가능하다.
$query
->join('users') // Query Builder 반환
->on(...); // Query Builder에는 on()이 없음
변수나 메서드를 사용할 때는 해당 변수나 객체가 실제로 그 기능을 가지고 있는지 확인해야 한다.
마찬가지로 on() 역시 현재 체이닝 중인 객체가 아니라 JoinClause 객체에 존재하는 메서드이므로 직접 호출할 수 없다.
올바른 사용 방법
join() 내부에 클로저를 전달하면 Laravel이 JoinClause 객체를 생성하여 전달해 준다.
그 안에서 on()을 사용해야 한다.
$query->join('users', function ($join) {
$join->on('users.id', '=', 'posts.user_id');
});
정리
-
join()호출 후 반환되는 것은 Query Builder 객체이다. -
on()메서드는 Query Builder가 아닌 JoinClause 객체에 존재한다. -
따라서
on()은 반드시join()내부의 클로저에서 사용해야 한다. -
Laravel Query Builder를 사용할 때는 메서드 체이닝보다 현재 어떤 객체가 반환되고 있는지 확인하는 습관이 중요하다.
나의 정리
join을 실행한 시점에서 쿼리빌더객체가 반환됨
근데 쿼리빌더객체가 on메서드를 가지고있지 않음
on은 쿼리빌더객체가 아니라 join객체가 내부에서 가짐
그렇기 때문에 join객체 내부에 클로저로 전달해야한다