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[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 [2],有人名、地址、電話、mail、網址、公司名稱、日期時間,連信用卡、顏色、檔案、圖片等等都有。

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