前言 本文以「一個使用者擁有多個專案和多筆文章」為例,為關聯模型建立資料填充。
關聯方法 首先,為 User
模型建立 projects()
和 posts()
關聯方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public function projects ( ) { return $this ->hasMany (Project ::class ); } public function posts ( ) { return $this ->hasMany (Post ::class ); }
做法一 以父模型為主,由上而下建立關聯資料。
首先,建立一個 UserSeeder
資料填充,建立 5 個使用者,為每個使用者建立 10 個專案和 10 筆文章。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 use App \Post ;use App \Project ;use App \User ;use Illuminate \Database \Seeder ;class UserSeeder extends Seeder { public function run ( ) { factory (User ::class , 5 )->create ()->each (function ($user ) { $user ->projects ()->saveMany (factory (Project ::class , 10 )->make ()); $user ->posts ()->saveMany (factory (Post ::class , 10 )->make ()); }); } }
此方法將所有模型都寫在同一個檔案,在互相關聯的情況下,很容易寫出複雜的巢狀結構,不易維護。
做法二 將模型工廠生成的測試資料儲存在靜態屬性中,讓測試資料可以在不同的 Seeder 之間分享。
首先,在 App\Traits
資料夾建立一個 HasStaticAttributes
特徵機制:
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 trait HasStaticAttributes { private static array $attributes = []; private function setAttribute (string $key , $value ) { self ::$attributes [$key ] = $value ; } private function getAttribute (string $key ) { return self ::$attributes [$key ] ?? null ; } public function set (string $key , $value ) { $this ->setAttribute ($key , $value ); } public function get (string $key ) { return $this ->getAttribute ($key ); } public function __set (string $key , $value ) { $this ->setAttribute ($key , $value ); } public function __get (string $key ) { return $this ->getAttribute ($key ); } public function __call ($method , $parameters ) { return $this ->getAttribute ($method ); } }
建立一個 UserSeeder
資料填充,引入特徵機制,建立 5 個使用者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 use App \User ;use App \Traits \HasStaticAttributes ;use Illuminate \Database \Seeder ;class UserSeeder extends Seeder { use HasStaticAttributes ; private const AMOUNT = 5 ; public function run ( ) { $this ->users = factory (User ::class , self ::AMOUNT )->create (); } }
建立一個 ProjectSeeder
資料填充,引入特徵機制,從 UserSeeder
取得測試資料,並為每個使用者建立 10 個專案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 use App \Project ;use App \Traits \HasStaticAttributes ;use Illuminate \Database \Seeder ;class ProjectSeeder extends Seeder { use HasStaticAttributes ; private const AMOUNT = 10 ; public function run ( ) { app (UserSeeder ::class )->users->each (function ($user ) { $user ->projects ()->saveMany (factory (Project ::class , self ::AMOUNT )->make ()); }); } }
建立一個 PostSeeder
資料填充,引入特徵機制,從 UserSeeder
取得測試資料,並為每個使用者建立 10 筆文章。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 use App \Post ;use App \Traits \HasStaticAttributes ;use Illuminate \Database \Seeder ;class PostSeeder extends Seeder { use HasStaticAttributes ; private const AMOUNT = 10 ; public function run ( ) { app (UserSeeder ::class )->users->each (function ($user ) { $user ->posts ()->saveMany (factory (Post ::class , self ::AMOUNT )->make ()); }); } }
此方法避免將所有模型都寫在同一個檔案內,而是利用靜態屬性分享測試資料,靈活度比較高。