이제 실제 일정 관리 서비스 개발을 위해 컨트롤러와 모델을 만들 차례로 더 빠른 개발을 위해 라라벨의 스캐폴딩 기능을 사용하여 컨트롤러와 모델의 골격을 만들 것입니다. 

컨트롤러와 모델 생성

artisan make:model 명령어를 사용하여  Project와 Task 모델을 생성합니다.

모델 생성

$ php artisan make:model Project
$ php artisan make:model Task
BASH

 

이제 artisan make:controller 명령으로 컨트롤러를 생성하며 RESTFul 컨트롤러로 만들기 위해 --plain 옵션을 주지 않습니다.

컨트롤러 생성

$ php artisan make:controller ProjectController --resource
BASH

5.1 사용자는 --resource 옵션을 제외해야 합니다.

이제 Task 컨트롤러를 작성할 순서이며 태스크는 프로젝트에 포함되므로 라우팅과 컨트롤러도 계층적으로 만들어 주는 것이 관리 측면에서 유용하며 다음과 같은 방법이 있습니다.

  1. 하위 디렉터리에 컨트롤러를 작성하며 이경우 app/Http/Controllers/Project 폴더를 만들고 하위 컨트롤러인 TaskController 를 이 안에 넣어주며 컨트롤러가 많을 경우 관리가 용이하므로 유용한 방법입니다.

    이 경우 라우팅은 다음과 같이 \ 를 구분자로 하여 넣어 주면 됩니다.
    Route::resource('project.task', 'Project\TaskController'); 
    CODE
  2. 같은 레벨로 컨트롤러를 위치시키며 대신 컨트롤러 이름에 부모 컨트롤러를 접두사로 붙입니다. 즉 Project 하단의 Task 컨트롤러가 있을 경우 ProjectTaskController 로 명명하며 다음과 같이 라우팅을 설정합니다.

    Route::resource('project.task', 'ProjectTaskController'); 
    CODE



실전 프로젝트는 컨트롤러가 많지 않으므로 2번 방식에 따라 계층적인 컨트롤러를 작성하겠으며 다음 artisan 명령어를 실행합니다.

$ php artisan make:controller ProjectTaskController --resource
CODE

 

모델간 관계 설정

이제 설계한 스키마에 맞게 각 모델들간의 관계를 설정해 봅시다. 먼저 사용자 정보를 담고 있는 User.php 에 다음 두 가지 메소드를 구현합니다.

User.php

public function projects() // 1
{
    return $this->hasMany(Project::class);
}

public function tasks() //2
{
    return $this->hasManyThrough(Task::class, Project::class);
}
PHP
  • 1:  사용자는 다수의 프로젝트를 소유할 수 있으므로 hasMany() 관계로 설정합니다.
  • 2:  사용자의 task에 바로 접근할 수 있도록 HasManyThrough 관계를 설정하며 첫 번째 파라미터는 접속할 최종 모델을 기술하며 두 번째 파라미터는 거쳐갈 중간 모델을 기술합니다. 사용자는 Project 모델을 통해 Task 모델에 소유한 모든 Task 모델을 가져올 수 있습니다.

이제 프로젝트 정보를 담고 있는 Project 모델을 수정합니다.

Project.php

class Project extends Model
{
    protected $fillable = ['name', 'description', ];	//1

    public function tasks()	// 2
    {
        return $this->hasMany(Task::class);
    }

    public  function user() //3
    {
        return $this->belongsTo(User::class);
    }
}
CODE
  • 1 : 모델을 통해 데이타를 삽입할 수 있도록 $fillable 변수를 통해 화이트 리스트에 추가합니다.
  • 2 : 프로젝트는 다수의 task를 가질 수 있으므로 hasMany() 관계를 설정합니다.
  • 3:  프로젝트는 하나의 사용자에 속하므로 belongsTo() 관계를 설정합니다.
 

이제 할일을 담고 있는 Task 클래스를 설정합니다.

Task.php

class Task extends Model
{
    protected $fillable = ['name', 'description', 'due_date', 'priority', 'status'];  // 1

	protected $dates = ['due_date'];	//2
    public function project() // 3
    {
        return $this->belongsTo(Project::class);
    }

    public function scopeDueInDays($query, $days)  // 4
    {
        $now = \Carbon\Carbon::now();	// 5
        return $query->where('due_date', '>', $now)  // 6
            ->where('due_date', '<', $now->copy()->addDays($days));  // 7
    }
}
CODE
  • 1 : 모델을 통해 데이타를 삽입할 수 있도록 $fillable 변수를 통해 화이트 리스트에 추가합니다.
  • 2 : 기존의 두 개의 타임스탬프 컬럼(created_at, updated_at) 외에 추가로 due_date 컬럼도 날자 타입임을 지정하며 자세한 내용은 REF: 관례(Convention) 중 "타임스탬프와 dates" 항목을 참고하세요.

  • 3 : task는 하나의 프로젝트에 속하므로 belongsTo() 메소드로 관계를 설정합니다.
  • 4 : 특정 기간내에 만료되는 task를 가져오기 위한 메소드를 정의하며 첫 번째 파라미터는 쿼리 빌더 객체이며 두 번째는 integer 값으로 유효 기간 만료일입니다.
  • 5: Carbon 패키지로 현재 시간을 가져옵니다.
  • 6: where()  조건에 현재 시간보다 큰 데이타를 추가합니다.
  • 7: where()  조건에 파라미터로 넘어온 날자를 추가하며 파라미터가 3일 경우 최종 쿼리는 종료일이 현재일부터 3일 이내인 데이타를 가져오게 됩니다.

이제 테이블 간의 관계를 작성하였고 설정한 관계를 테스트 하는 손쉬운 방법은 직접 데이타를 가져오는 것이지만 아직 데이타가 없어서 테스트를 할 수 없습니다.

라라벨의 모델 팩토리 기능을 사용하여 의미있는 테스트 데이타를 생성하고 모델간의 관계를 확인해 봅시다.