# Migrations & Seeding

## Migrations

依 Laravel 官網上的說明，Migrations 是一種資料庫的版本控制。它可以讓開發團隊在修改資料庫綱要(schema)時仍保持最新的狀態。Migrations 使用 Schema Builder 來管理資料庫。

### 建立 Migrations

在終端機中，進入網站根目錄，輸入指令：

```
php artisan migrate:make create_users_table
```

會產生類似

```
app/database/migrations/2014_12_11_081527_create_posts_table.php
```

這樣的檔案。你所輸入的檔案前面會加上日期及時間戳記，日期及時間戳記在每次執行指令建立檔案時都會不同，也就是說，之後在執行 migrate 動作時，它是會依序執行的。如果你有要調動執行的順序，只要改前面的日期或時間戳記，就能改變被執行的順序。

### 執行 Migrations

在終端機輸入指令：

```
php artisan migrate
```

這個指令會將 app/database/migrations 目錄下的所有 migrations 檔全部執行。

而且它會記得上次執行的 migrate 動作。例如：你今天新增了 3 個 migrations 檔，並且執行過 migrate 的動作。當你隔天又加入新的 migrations 檔時，它只會對新的檔案動作，所以在紀錄中，你總共執行過兩次 migrate 的動作。

### 倒回(rollback)上一次的 Migrate 動作

指令：

```
php artisan migrate:rollback
```

因為是還原上一次的動作，也就如果你執行過 3 次 migrate 指令，那就只會還原最近這一次的動伯。如果想要還原到最初的狀態，就必須重覆執行，直到它告訴你沒有動作可以還原了為止，當然有其他指令可以達成這個要求，使用：

```
php artisan migrate:reset
```

重置到最原始狀態。

如果要全部還原，然後重做 migrate，可以執行：

```
php artisan migrate:refresh
```

等同於 migrate:reset 加上 migrate，簡直就是懶人的天堂。

！重要：你很可能在執行 migrate 指令時會遇到 "class not found" 的錯誤，這是因為 artisan 不知道你有新增類別，也就是新建立的 mirgate 檔案。可以執行指令：

```
php artisan dump-autoload
```

來載入這個新建的類別，這個指令還滿常用的，有時候新建 controller 後也會用到。

## Seeding

有時候我們會需要預先建立一些假資料來測試，這時候利用 Laravel 提供的 Seeding 功能，非常方便就能完成。檔案存放目錄在：

```
app/database/seeds
```

檔案命名沒有強制規定。

在 seeds 目錄中己經有一個 DatabaseSeeder.php 檔，你可以在這個檔案中使用 call() 方法去呼叫你建立的 seeding 檔，它會依你呼叫的順序執行。

現在，新增一個 PostTableSeeder.php 檔：

```
<?php

class PostTableSeeder extends Seeder {

    public function run()
    {
        DB::table('posts')->delete();
        Post::create(['title' => 'Hello!!!', 'content' => 'Laravel~~~']);
    }

}
```

在 run 裡面的第一行，通常會先把已存在的資料全部刪除，如果你不這麼做，資料將會一直增加。

接著在 DatabaseSeeder.php 檔的 run() 中加入：

```
$this->call('PostTableSeeder');
```

這樣當 DatabaseSeeder 被執行時，就會去呼叫我們的 PostTableSeeder。

當你把所有的 XxxSeeder 檔都建好後，就可以執行指令了：

```
php artisan db:seed
```

在 Seeder 檔中指定的資料就會全部加入資料庫了。

你可以在 call() 方法之後加上：

```
$this->command->info('Post table seeded!');
```

這樣會在終端機顯示一行文字 ('Post table seeded!')，告訴執行指令的人，這個 seed 動作已完成。

預設 db:seed 指令會去執行 DatabaseSeeder 類別，然後由它去呼叫其他的 Seeder，如果你想直接執行某個 Seeder，可以在指令上加入想執行的類別：

```
php artisan db:seed --class=PostTableSeeder
```

這樣就只會單獨執行 PostTableSeeder。

前面提到的 migrate:refresh 可以在後面加上 --seed 參數，達到重置資料表並同時執行 seed 的動作：

```
php artisan migrate:refresh --seed
```

註：如果你在執行 seed 指令的時候出現錯誤：

```
[Illuminate\Database\Eloquent\MassAssignmentException]
title
```

這是說你無法對該欄位(這裡顯示 'title')做大量指派，因為我們使用 Post::create() 方法，會觸發大量指派的檢查。在 Eloquent ORM 這節我們有提到，如果要對某欄位大量指派，必須設定 fillable 欄位。

所以記得在 app/models/Post.php 加入：

```
protected $fillable = ['title', 'content'];
```

### 看起很真的假資料

#### 安裝 Faker

利用 [Faker](https://packagist.org/packages/fzaninotto/faker)\[1] 可以建立以假亂真的資料，省得老是為了輸入假資料而煩惱。不過目前只有英文內容。

首先要在你的專案中安裝 Faker 套件。開啟專案(網站)中的 composer.json 檔，加入：

```
"require-dev": {
  "fzaninotto/faker": "1.5.*@dev"
}
```

你可以在最後一個項目後面加上逗號，之後再貼上上面這段程式碼。儲存後，接著在終端機輸入指令：

```
composer update
```

要等一段時間更新，它會去下載 Faker 套件。

#### 使用 Faker

開啟 app/database/seeds/PostTableSeeder.php，先引入 Faker 的命名空間，寫在 class 前面：

```
<?php
use Faker\Factory as Faker;
class PostTableSeeder extends Seeder {
//略⋯⋯
```

之後我們用到的 Faker 就是指 Faker\Factory 。現在將原本 Post::create() 這行改為：

```
$faker = Faker::create();

foreach (range(1, 10) as $i) {
    Post::create(['title' => $faker->sentence, 'content' => $faker->text]);
}
```

使用迴圈來一次建立 10 筆資料，$faker->sentence 會產生一段句子。$faker->text 會產生一段比較長的文字。

Faker 更多的資料格式，可以參考 [fzaninotto/Faker ](https://github.com/fzaninotto/Faker)\[2]，有人名、地址、電話、mail、網址、公司名稱、日期時間，連信用卡、顏色、檔案、圖片等等都有。

現在可以執行 seed 指令，看看加入的假資料看起來如何。

* \[1] <https://packagist.org/packages/fzaninotto/faker>
* \[2] <https://github.com/fzaninotto/Faker>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tony915.gitbook.io/laravel-4-2/database/migrations-and-seeding.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
