뷰에서 태스크 목록은 표시되지만 아직 검색 기능이 동작하지 않으므로 구현해 봅시다.

 

가장 먼저 만료일이 특정 기간안에 있는 기능을 구현하겠으며 편리하게 쓸수 있도록 REF:쿼리 스코프(Query Scope)를 사용하겠습니다. 모델 클래스인 Task.php 를 열어서 다음 쿼리 스코프를 구현합니다.

class Task extends Model
{
 
public function scopeDueDateBetween($query, \Carbon\Carbon $start_date, \Carbon\Carbon $end_date)	//1
{
    return $query->whereBetween('due_date', [
        $start_date->startOfDay(), // 2
        $end_date->endOfDay()
    ]);
}
CODE
  • 1 : 접두사로 scope를 붙여서 메소드를 선언합니다. 파라미터 선언은 객체 타입까지 힌팅하면 잘못된 데이타를 넘기는 실수를 방지할수 있고 IDE 에서 메소드 자동 완성이 되므로 편리합니다.
  • 2 : whereBetween( string $column, array $values, string $boolean = 'and') 메소드를 사용하여 범위를 설정합니다. 카본의 startOfDay() 는 메소드는 그날의 시작 시간(00:00:00)을 endOfDay() 는 마지막 시간(23:59:59)를 리턴합니다.

상태와 우선 순위 필드 검색을 위해 Task 모델 클래스에 Request 객체를 파라미터로 받는 쿼리 스코프를 추가합니다.

class Task extends Model
{
 
public function scopeOtherParam($query, \Illuminate\Http\Request $request)
{
    $priority = $request->get('priority');
    if (!empty($priority) && $priority != 'all') {	// 1
        $query = $query->where('priority', $priority);	
    }

    $status = $request->get('status');
    if (!empty($status) && $status != 'all') {	// 2
        $query = $query->where('status', $status);
    }

    return $query;		// 3
}
CODE
  • 1,2 : priority, status 필드가 있고 값이 'all' 이 아닐 경우 쿼리에 추가하며 쿼리 빌더에서 where priority = $priority 와 같이 SQL 구문으로  변환됩니다.
  • 3 : 최종 생성된 쿼리 객체를 리턴합니다.

 

이제 컨트롤러의 index() 메소드를 구현하며 브라우저가 전송한 검색 필드를 사용하기 위해 Request $request 를 파라미터에 추가합니다.

 public function index(Request $request)
{
    $user = \Auth::user();

    if(!empty($request->get('start_date'))) {	// 1
        $start_date = Carbon::createFromFormat('Y-m-d H:i:s', $request->get('start_date'));
    } else {
        $start_date = Carbon::now();
    }

    if(!empty($request->get('end_date'))) {		//2
        $end_date = Carbon::createFromFormat('Y-m-d H:i:s', $request->get('end_date'));
    } else {
        $end_date = $start_date->copy()->addMonths(1);
    }

    $tasks = $user->tasks()
            ->dueDateBetween($start_date, $end_date)	//3
            ->otherParam($request)						//4
            ->orderBy('due_date', 'desc')
            ->get();

    return view('task.index')
        ->with('tasks', $tasks)
        ->with('start_date', $start_date)
        ->with('end_date', $end_date)
        ->with('status', $request->get('status'))
        ->with('priority', $request->get('priority'));
}
CODE
  • 1: start_date 필드가 있을 경우 문자열 형식으로부터 카본 객체로 변환하며 값이 없을 경우 현재 시간으로 설정합니다. 

    실제 서비스 환경에서는 잘못된 값이 넘어오면 카본 객체에서 예외를 던지므로 예외 처리 로직을 구현 해야 합니다.

  • 2: end_date 필드로 카본 객체를 사용하며 값이 설정되지 않았을 경우 $start_date 에 한 달을 더한 날자로 설정합니다.
  • 3: 쿼리 스코프를 사용하여 기한 필드의 검색 범위를 설정합니다.
  • 4: 쿼리 스코프를 사용하여 status, priority 필드 검색 조건을 추가합니다. 이렇게 구현해 놓으면 향후 새로운 검색 필드가 추가되도 컨트롤러는 변경할 필요 없이 쿼리 스코프 메소드만 수정하면 됩니다.

 

검색 기능 구현이 완료되었고 독자들은 라라벨의 쿼리 스코프와 ORM 을 사용하면 아주 쉽고 확장성 있게 기능을 구현할 수 있는 것을 확인했을 것입니다.

이제 브라우저로 연결하여 검색 기능이 제대로 동작하는지 검색 조건을 변경해 가며 확인해 봅시다.