DB 시딩과 모델 팩토리를 사용하여 초기 데이타를 생성하기 위해서 먼저 database/factories/ModelFactory.php  를 에디터로 열어봅시다.

$factory->define(App\Project::class, function (Faker\Generator $faker) {
    // 집계함수를 사용하여 id 의 최소, 최대값을 가져옴
    $min = App\User::min('id');  // 1
    $max = App\User::max('id');  
    return [
        'user_id' => $faker->numberBetween($min, $max),	// 2
        'name' => substr($faker->word, 0, 20),			// 3
        'description' => $faker->sentence,				// 4
        'created_at' => $faker->dateTimeBetween($startDate = '-2 years', $endDate = '-1 years'),	//5
        'updated_at' => $faker->dateTimeBetween($startDate = '-1 years', $endDate = 'now'),			//6
    ];
});

$factory->define(App\Task::class, function (Faker\Generator $faker) {
    // 집계함수를 사용하여 id 의 최소, 최대값을 가져옴
    $min = App\Project::min('id');
    $max = App\Project::max('id');

    $dt = $faker->dateTimeBetween($startDate = '-1 months', $endDate = 'now');	// 7

    return [
        'project_id' => $faker->numberBetween($min, $max),
        'name' => substr($faker->sentence, 0, 20),
        'description' => $faker->text,
        'due_date' => $faker->dateTimeBetween($startDate = '-1 months', $endDate = '+1 months'),	// 8
        'created_at' => $dt,
        'updated_at' => $dt,
    ];
});
CODE
  • 1: Project 모델은 User 테이블의 user_id 를 참조 키로 설정해야 하므로 사용자 id 의 최소,최대 값을 집계 함수(min, max)를 사용하여 가져옵니다.
  • 2: user_id 가 project 에 고르게 배분되도록  numberBetween 메소드에 min, max를 파라미터로 전달하여 실행합니다. 
  • 3,4: 프로젝트의 이름, 설명에 사용할 랜덤한 문자열을 생성합니다.
  • 5, 6: time stamp 컬럼에 사용할 Date 를 구간안에서 랜덤하게 생성합니다.
  • 7: 할일 테이블에 설정할 생성일을 한달내에서 랜덤하게 생성합니다.
  • 8: 완료일을 지난 한달과 앞으로 한달 사이에 랜덤하게 생성합니다. 설정한 완료일은 Task 모델의 scopeDueInDays() 메소드를 사용하여 기간내 완료 할일을 찾는 기능을 테스트하기 위해 필요합니다.

 

설정이 끝났으면 위 모델 팩토리를 사용하는 시딩을 생성합니다.

 

$ php artisan make:seeder TaskTableSeeder
 
Seeder created successfully.
CODE

 

생성된 시딩 파일(database/seeds/TaskTableSeeder.php) 파일을 에디터로 열어서 모델 팩토리로 테스트 데이타를 생성하는 코드를 추가합니다.

public function run()
{
    $array = [	// 1
        '개인' => '개인적으로 할 일',
		'작업' => '업무 목록',
		'심부름' => '심부름',
		'쇼핑' => '사야할 것들',	
    ];

    $users = App\User::all();	// 2

    foreach($users as $u) {		//3 
        foreach ($array as $name => $desc) {	//4
            $proj = factory(App\Project::class, 1)	//5
                ->create([
                    'name' => $name,
					'description' => $desc,
                    'user_id' => $u->id,
                ]);

            foreach (factory(App\Task::class, 10)->make() as $task) {	//6
                $proj->tasks()->save($task);
            }
        }
    }
}
CODE
  • 1: 사용자마다 초기에 설정해줄 프로젝트의 목록입니다.
  • 2, 3: 모든 사용자의 정보를 가져와서 반복문을 수행합니다.
  • 4: 프로젝트의 목록수 만큼 반복문을 수행합니다.
  • 5: Project 모델을 한 개 생성하여 DB 에 입력하며 name, description user_id 필드의 값은 모델 팩토리로 생성한 값을 사용하지 않고 각 배열의 요소를 사용합니다.
  • 6: 생성된 프로젝트마다 모델 팩토리로 10개의 태스크를 생성한 후에 foreach 로 각 Task 모델을 프로젝트 모델과 연결한 후에 DB 에 저장합니다.

 

이제 시딩 클래스를 구현했으므로 database/seeds/DatabaseSeeder.php 를 열어서 run() 메소드에 구현한 클래스를 추가합니다.

public function run()
{
    $this->call(UserTableSeeder::class);
    $this->call(TaskTableSeeder::class);	//추가
}
CODE

이제 테스트 데이타를 생성할 모든 준비가 끝났고 artisan 을 실행해서 시딩을 적용합니다.

$ php artisan db:seed --class=TaskTableSeeder
CODE

--class 옵션으로 시딩할 클래스를 직접 지정한 이유는 이미 UserTable은 시딩을 하였으므로 에러가 발생할 수 있기 때문입니다. 

 

만약 artisan db:seed 실행시 다음 에러가 발생하면 composer dump-autoload 를 실행해 줍니다.

 

[ReflectionException]
Class TaskTableSeeder does not exist

 

이제 전 절에서 작성한 모델간의 관계가 잘 동작하는지 직접 데이타를 가져와 보기 위해 팅커를 구동합니다.

$ php artisan tinker 
CODE

 

팅커 쉘에서 사용자 id가 1인 사용자의 모든 프로젝트를 가져오는 다음 코드를 실행하여 정상적으로 데이타를 가져 오는지 확인해 봅시다.

>>> $prj = App\User::find(1)->projects()->get()
=> Illuminate\Database\Eloquent\Collection {#694
     all: [
       App\Project {#695
         id: 2,
         user_id: 1,
CODE

 

이번에는 hasManyThrough 를 확인하기 id가 1인 사용자의 모든 할일을 가져와 보는 코드를 실행해 봅시다.

>>> $tasks = App\User::find(1)->tasks()->get()
 
=> Illuminate\Database\Eloquent\Collection {#970
    all: [
        App\Task {#770
        id: 1,
CODE

모델간의 관계가 잘 동작하는 것을 확인할 수 있으며 이제 성공적으로 컨트롤러와 모델을 만들고 설정 했으므로 라우팅에 등록할 순서입니다.