Home 라라벨로 배우는 php 웹 프로그래밍
Post
Cancel

라라벨로 배우는 php 웹 프로그래밍

라라벨로 배우는 실전 PHP 웹 프로그래밍

PART 1 라라벨 입문

11. 데이터베이스 시딩

데이터베이스 테이블에 데이터를 심는 행위를 시딩이라고 한다.

시딩은 서비스 구성에 필요한 기본 데이터, 개발 중에 필요한 데이터, 테스트를 위한 데이터를 빠르게 준비할 때 사용한다. 그리고 라라벨은 클래스 문법으로 데이터 시딩을 자동화할 수 있는 방법을 제공한다.

11.1 시더 만들기

시더 클래스 뼈대 코드 만들기

1
2
$ php artisan make:seeder UsersTableSeeder
Seeder created successfully.

방금 만든 시더 클래스는 database/seeds 디렉터리 아래에 있다. 파일을 열어서 내용을 채워보자

database/seeds/UsersTableSeeder.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        App\User::create([
            'name' => sprintf('%s %s',str_random(3),str_random(4)),
            'email' => str_random(10).'@example.com',
            'password' => bcrypt('password'),
        ]);
    }
}

시더 클래스의 이름은 자유롭게 지을 수 있다. 아티즌의 시딩 명령이 시더 클래스의 run() 메서드를 실행한다. 따라서 시딩 로직을 run() 안에 넣어야 한다.

  • str_random(int $length = 16)
    라라벨 도우미 함수. $length 바이트짜리 랜덤 문자열을 반환한다.
  • sprintf(string $format, mixed $args = null)
    php 내장함수. sprintf 함수 대신 str_random(3).’ ‘.str_random(4)와 같이 바꾸어 쓸 수 있다.

이제 아티즌 멸령줄로 시딩을 하고, 데이터베이스에서 결과를 확인한다.

데이터베이스 시더 실행

1
2
$ php artisan db:seed --class=UsersTableSeeder
Database seeding completed successfully.

11.2 모델 팩토리

모델 팩토리는 더미 데이터를 빠르게 만들기 위한 도구다. 팅커 콘솔로 모델 팩토리를 이용해 보자.

모델 팩토리 맛보기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ php artisan tinker
Psy Shell v0.9.12 (PHP 7.3.11 — cli) by Justin Hileman
>>> factory(App\User::class)->make();
=> App\User {#3198
     name: "Jefferey Pouros",
     email: "helga.will@example.net",
     email_verified_at: Illuminate\Support\Carbon @1612358212 {#3194
       date: 2021-02-03 13:16:52.342677 UTC (+00:00),
     },
   }
>>> factory(App\User::class)->make(['name'=>'Foo']);
=> App\User {#3207
     name: "Foo",
     email: "brad.schowalter@example.com",
     email_verified_at: Illuminate\Support\Carbon @1612358244 {#3208
       date: 2021-02-03 13:17:24.870220 UTC (+00:00),
     },
   }
>>> 

위 명령은 실행할 때마다 다른 값을 출력한다.

factory(string $class, int $amount = 1)는 도우미 함수다. $amount 인자는 생략할 수 있다. $amount 인자를 쓰면 지정된 수 만큼의 $class 인스턴스를 만든다.

make(array $attributes = []) 메서드는 모델 팩토리가 임의로 채운 값을 이용해서 새로운 모델 인스턴스를 만든다. $attributes 인자를 넘기면 임의 값을 오버라이드할 수 있다

11.2.1 시더 수정

make() 메서드는 모델 인스턴스를 만들기만 한다. 모델을 데이터베이스에 저장하려면 create(array $attributes = []) 메서드를 사용한다. 모델 팩토리를 이용하여 앞서 만든 시더 클래스를 수정하다.

database/seeds/UsersTableSeeder.php ```php <?php

use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { factory(App\User::class, 5)->create(); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
아티즌 명령줄로 시딩을 하면(php artisan db:seed) users 테이블에 다섯 명의 새로운 사용자가 만들어진다.

#### 11.2.2 모델 팩토리 추가

모덾 팩토리는 users 테이블 스키마를 어떻게 알았을까? 프레임워크 어딘가에서 모델 팩토리를 선언하고 있지는 않을까? 혹 여러분의 모델 팩토리가 아래와 다르다면 반드시 수정하기 바란다.

> database/factories/UserFactory.php

```php
<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */
use App\User;
use Illuminate\Support\Str;
use Faker\Generator as Faker;

/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/

$factory->define(User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->safeEmail,
        'password' => bcrypt('password'), // password
        'remember_token' => Str::random(10),
    ];
});
  • ModelFactory.php, $factory
    이 파일은 라우팅 정의처럼 다른 클래스가 참조하기 위해 사용하는 파일이다. 이 파일에는 $factory라 변수가 이미 선언되어 있다. 이 변수는 Illuminate\Database\Eloquent\Factory 클래스의 인스턴스라 define(string $class, callable $attribute ) 메서드를 쓸 수 있다. define() 메서드의 첫 번째 인자는 모델 이름이며, 두 번쩨 인자는 콜백이다.

  • $faker
    콜백은 Faker\Generator $faker 인스턴스를 인자로 받고 배열을 반환한다. 콜백 안에서는 인자로 받은 $faker 변수의 메서드를 이용해서 모델 프로퍼티에 채울 임의의 값을 연관 배열로 만들어 반환한다. $faker 의 메서드들은 fzaninotto/faker 문서에서 확인할 수 있다(이 컴포넌트는 composer.json에 의존성으로 선언되어 있다.)

    Article 모델 팩토리를 정의하고 새로운 시더를 만들자. user_id 열이 없다는 점을 눈여겨보자. 아래의 코드를 보면 $faker->dateTimeThisMonth;는 그 뜻을 직관적으로 알 수 있다.

database/factories/UserFactory.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  <?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */
use App\User;
use Illuminate\Support\Str;
use Faker\Generator as Faker;

/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/

$factory->define(User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->safeEmail,
        'password' => bcrypt('password'), // password
        'remember_token' => Str::random(10),
    ];
});


$factory->define(App\Article::class, function (Faker $faker) {
    $date = $faker->dateTimeThisMonth;

    return [
        'title' => $faker->sentence(),
        'content' => $faker->paragraph(),
        'created_at' => $date,
        'updated_at' => $date,
    ];
});


articles 테이블 시더 뼈대 코드 만들기

1
2
$ php artisan make:seeder ArticlesTableSeeder
Seeder created successfully.

database/seeds/ArticlesTableSeeder.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

use Illuminate\Database\Seeder;

class ArticlesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $users = App\User::all();

        $users->each(function($user){
            $user->articles()->save(
                factory(App\Article::class)->make()
            );
        });
    }
}
  • $users->each( … ); 모델 팩토리에 user_id 정의가 없으므로 사용자와의 관계를 이용해서 포럼 글을 만든다. $users 변수에 사용자 컬렉션을 담고, 컬렉션을 순회하면서 포럼 글을 만드는 식으로 짰다. 엘로퀀트 컬렉션에서 쓸 수 있는 each 메서드를 이용했는데, foreach($users as $user){ … } 를 사용해도 무방하다.
  • $user->articles()->save( … ); make() 메서드는 새로운 모델 인스턴스를 반환하고 데이터베이스에 저장하지는 않는다. 방금 만든 모델 인스턴스는 sava(\Illuminate\Database\Eloquent\Model $model) 메서드의 인자로 대입되었다. save() 메서드는 create(array $attributes = []) 와 같은 일을 하는데, 받을 수 있는 인자의 타입만(객체와 배열) 다르다.

11.3 마스터 시더

모델마다 아티즌 시딩 명령을 수행하는 것은 번거롭다. 라라벨은 시더 클래스를 등록할 수 있는 마스터 시더 클래스를 제공한다. 이 레지스트리가 필요한 이유는 시딩의 순서 때문이다. 마이그레이션할 때 외래 키와 연결할 다른 테이블의 열이 없으면 오류가 발생했다. 시딩도 마찬가지다.

database/seeds/DatabaseSeeder.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        if (config('database.default') !== 'sqlite'){
            DB::statement('SET FOREIGN_KEY_CHECKS=0');
        }

        App\User::truncate();
        $this->call(UsersTableSeeder::class);

        App\Article::truncate();
        $this->call(ArticlesTableSeeder::class);

        if (config('database.default') !== 'sqlite'){
            DB::statement('SET FOREIGN_KEY_CHECKS=1');
        }

    }
}

아티즌 명령중로 시딩하고, 테이블에서 결과를 확인하자.

데이터베이스 시딩

1
2
3
4
$ php artisan db:seed
Seeding: UsersTableSeeder
Seeding: ArticlesTableSeeder
Database seeding completed successfully.
  • config(‘database.default’)
    mysql을 반환한다. config/database.php 파일에서 default 키에 할당된 값을 읽어오는 구문이다.
    데이터베이스 마이그레이션에서 FOREIGN_KEY_CHECKS를 본 적이 었다. 데이터를 변경 할 때 외래 키 체크를 잠시 꺼두기 위한 데이터베이스 구문이다. SQLite 데이터베이스는 이 구문을 지원하지 않기 때문에 예외 처리한 것이다. FOREIGN_KEY_CHECKS 설정을 끄지 않고 시딩을 실행하면 Illuminate\database\QureyException 이 발생한다. 시딩이 끝났으면 다시 켜야 한다

  • truncate() 이 메서드는 테이블에 담긴 모든 데이터를 버린다. 데이터를 지운다는 측면에서 delete()메서드와 같지만, 이 메서드는 기본 키를 1부터 재배열한다는 점이 다르다.

  • call(string $class) 이 메서드는 $class::run() 메서드의 본문을 실행하고 콜솔에 결과를 출력한다. call() 메서드는 부모 클래스에서 찾을 수 있다.

    11.4 마이그레이션과 시딩

    마이그레이션과 시딩 한 번에 실행하기

    1
    
    $ php artisan migrate:refreshh --seed
    
This post is licensed under CC BY 4.0 by the author.

라라벨로 배우는 php 웹 프로그래밍

라라벨로 배우는 php 웹 프로그래밍

Comments powered by Disqus.

Trending Tags