Laravel Seeder 基本實作

在寫程式時,時常很需要搭配資料來檢測程式是否有如預期的運作。
像是在做一個訂單列表頁,這個頁面就可能包含了訂單本身、購買人資訊、選購的商品、金額還有規格與名稱,甚至還有活動限定的優惠折扣等。
這時候若要產出一個最低需求的訂單資訊,可能就要手動從建立商品頁面一步一步的操作,接著切換到消費者頁面去實際去選購商品到購物車,然後下訂單。光是產生一個訂單就不知道要花多久的時間,如果這時資料庫臨時需要異動,上述過程又得再重複執行一次。
當然,也可能直接從資料庫寫資料,但根據我的經驗,這樣硬塞入的資料其準度並不太高,容易忽略環節,也不好操作,只比手動從介面寫入稍微快一點。
所以,這時候 Laravel 提供的 Seeder 功能就很好用啦!這是能依據程式碼來批量產生假資料的功能。通常會搭配 faker 隨機產生欄位所需要的值,接著看是要直接使用 Model 來建立資料或著引入其他程式邏輯還建立資料。
以建立會員為例,通常會先建立一個 MemberFactory 與 ArticleFactory 的檔案來產生假資料
php artisan make:factory MemberFactoryphp artisan make:factory ArticleFactory
接著填入測試資料需要的最少可測試的資料。預填入的資料可以使用 faker 套件、固定的值或原生 php 隨機產生的資料。底下有用到 static $password,是能將雜湊化過的密碼可被重複使用,這樣可以免去每次需要重新 hash 的系統資源。
$factory->define(Member::class, function (Faker $faker) {
static $password;
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'password' => $password ?? $password = bcrypt('testPassword'),
'county' => '臺北市',
'district' => '中山區',
'address' => '復興北路80號12樓',
];
});接著產生文章的資料
$factory->define(Article::class, function (Faker $faker) {
static $password;
return [
'title' => $faker->name,
'content' => $faker->text(300)
];
});在產生文章假資料的時候沒有填入 member_id ,是因為這樣就不用再到資料庫重新建立一個會員或著在從資料庫找一個會員來塞。雖然實際上可以這麼做,但對於要有系統性的產生測試資料,這麼做只是增加執行的時間。
接著建立 ArticleTableSeeder:
php artisan make:seeder ArticleTableSeeder首先在 ArticleTableSeeder 寫下產生會員與會員文章的數量
factory(Member::class, 10)->create()->each(function ($member) {$member->Articles()->saveMany(factory(Article::class,5)->make());$member->Articles()->save(factory(Article::class)->make([ 'title' => '自我介紹'
]));});
factory() 這個全域輔助方法可以在專案的任何地方使用,make() 方法可以將假資料做成一個物件,但實際還沒寫入資料庫,所以會搭配 save() 使用,因為這個方法沒辦法儲存字串或陣列。通常編寫 seeder 時會先寫 create(),在使用 each()來產生關聯資料(each()相當於 foreach loop,只是 each 需要使用 & 才能使用全域變數), 因為資料庫要先有資料並建立 id ,才能向外關聯外部資料。
make()與 create() 都可以寫入資料來覆寫 factory 預先定義的內容。當然不只這兩個方法可用,基本上 factory 相當於呼叫一個 Model ,所以 Model 能用的,這邊都能用,像是 update() 和 createOrUpdate() 等。
