Laravel - Database - Seeding

# 前言

學習一個框架, Ray 的想法是, 在深入理解底層實作的原理之前, 應該先知道這個框架的 使用方法; 先學習怎麼使用這個前人造的輪子, 再學習怎麼樣一個輪子。
所以本篇文章重點在於細讀官方文件, 並將內容理解後以 Q&A 的方式記錄下來, 加速學習以及查詢。

# Writing Seeders

以下 Laravel command 的意思是?
  • Example:
    php artisan make:seeder UserSeeder
  • Answer:
    建立一個 seed class
以下 Laravel example code 的意思是?
  • Example:
    <?php
    class DatabaseSeeder extends Seeder
    {
    public function run()
    {
    DB::table('users')->insert([
    'name' => Str::random(10),
    'email' => Str::random(10).'@gmail.com',
    'password' => Hash::make('password'),
    ]);
    }
    }
  • Answer:
    <?php
    class DatabaseSeeder extends Seeder
    {
    public function run()
    {
    DB::table('users')->insert([
    // 隨機產生 10
    'name' => Str::random(10),
    // 同上
    'email' => Str::random(10).'@gmail.com',
    // 將 string 'password' hash 存到資料庫
    'password' => Hash::make('password'),
    ]);
    }
    }

# Using Model Factories

以下 Laravel example code 的意思是?
  • Example:
    php artisan make:factory PostFactory --model=Post
  • Answer:
    建立一個 PostFactory, 該 factory 會產生 Post model
以下 Laravel example code 的意思是?
  • Example:
    <?php
    class UserFactory extends Factory
    {
    protected $model = User::class;

    public function definition()
    {
    return [
    'name' => $this->faker->name,
    'email' => $this->faker->unique()->safeEmail,
    'email_verified_at' => now(),
    'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
    'remember_token' => Str::random(10),
    ];
    }
    }
  • Answer:
    <?php
    class UserFactory extends Factory
    {
    // 該 factory 對應的 model
    protected $model = User::class;

    // 定義 model 預設的狀態
    public function definition()
    {
    return [
    'name' => $this->faker->name,
    'email' => $this->faker->unique()->safeEmail,
    'email_verified_at' => now(),
    'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
    'remember_token' => Str::random(10),
    ];
    }
    }
以下 Laravel 中, 位於 Factory 中的 example code 的意思是?
  • Example:
    <?php
    public function suspended()
    {
    return $this->state(function (array $attributes) {
    return [
    'account_status' => 'suspended',
    ];
    });
    }
  • Answer:
    自定義一個 factory method
以下 Laravel 中, 位於 Factory 中的 example code 的意思是?
  • Example:
    <?php
    class UserFactory extends Factory
    {
    protected $model = User::class;

    public function configure()
    {
    return $this->afterMaking(function (User $user) {
    //
    })->afterCreating(function (User $user) {
    //
    });
    }

    // ...
    }
  • Answer:
    <?php
    class UserFactory extends Factory
    {
    指定要建立的 model
    protected $model = User::class;

    public function configure()
    {
    // make model 後要做的事
    return $this->afterMaking(function (User $user) {
    //
    // create model 後要做的事
    })->afterCreating(function (User $user) {
    //
    });
    }

    // ...
    }
以下 Laravel 中, 位於 model 內的 example code 的意思是?
  • Example:
    <?php
    namespace App\Models;

    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;

    class User extends Model
    {
    use HasFactory;
    }
  • Answer:
    當特定 model 的 Factory 被定義後, 可在 model 中 use HasFactory trait, 這樣就可以在任何地方使用 static factory method
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    use App\Models\User;

    public function testDatabase()
    {
    $user = User::factory()->make();

    // Use model in tests...
    }
  • Answer:
    使用 factory 來 make 一個 User model, make 表示已建立但尚未儲存到資料庫
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $users = User::factory()->count(3)->make();
  • Answer:
    使用 user factory make 3 個 User model, make 表示已建立 model 但尚未儲存到資料庫
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    protected static function newFactory()
    {
    return \Database\Factories\Administration\FlightFactory::new();
    }
  • Answer:
    HasFactory trait 中的 factor method 有其規定的 convention, 像是 modelNameFactory, 如 PostFactory, 當使用 Post::factory() 時 Laravel 會自動尋找 Factory namespace 下面的 PostFactory
    上面的 example code 是當 Factory 不符合這個 convention 時, 可以特別指定
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $users = User::factory()->count(5)->suspended()->make();
  • Answer:
    suspended() 為自定義的 state method, 也可被使用
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $user = User::factory()->make([
    'name' => 'Abigail Otwell',
    ]);
  • Answer:
    一般來說, factory 會 return 在 factory 中定義好的 attributes, 但若臨時要特別指定 attributes, 可用以上的 example code
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $user = User::factory()->state([
    'name' => 'Abigail Otwell',
    ])->make();
  • Answer:
    一般來說, factory 會 return 在 factory 中定義好的 attributes, 但若臨時要特別指定 attributes, 可用以上的 example code
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    use App\Models\User;

    public function testDatabase()
    {
    $user = User::factory()->create();

    $users = User::factory()->count(3)->create();
    }
  • Answer:
    <?php
    use App\Models\User;

    public function testDatabase()
    {
    // 建立一筆 user model record 並 save
    $user = User::factory()->create();

    // 建立三筆 user model record 並 save
    $users = User::factory()->count(3)->create();
    }
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $user = User::factory()->create([
    'name' => 'Abigail',
    ]);
  • Answer:
    一般來說, factory 會 return 在 factory 中定義好的 attributes, 但若臨時要特別指定 attributes, 可用以上的 example code
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $users = User::factory()
    ->count(10)
    ->state(new Sequence(
    ['admin' => 'Y'],
    ['admin' => 'N'],
    ))
    ->create();
  • Answer:
    Sequence method 可以讓建立出來的 model 輪流使用帶入的參數, 所以這十筆 model 的資料就會是 y, n, y, n, …
以下的 Laravel Testing example code 的意思是?
  • Example:
    <?php
    $users = User::factory()
    ->count(10)
    ->state(new Sequence(
    fn () => ['role' => UserRoles::all()->random()],
    ))
    ->create();
  • Answer:
    當使用 Sequence() 時, 也可帶入 closure, 在建立每一個 model 時 closure 都會被 invoked
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    public function definition()
    {
    return [
    'user_id' => User::factory(),
    'user_type' => function (array $attributes) {
    return User::find($attributes['user_id'])->type;
    },
    'title' => $this->faker->title,
    'content' => $this->faker->paragraph,
    ];
    }
  • Answer:
    <?php
    public function definition()
    {
    return [
    // 建立 post 時, 同時建立一個 user
    'user_id' => User::factory(),
    // attributes 裡頭會有上一行建立的 user_id, 利用此 user_id 取得 User model 及
    // 其 type
    'user_type' => function (array $attributes) {
    return User::find($attributes['user_id'])->type;
    },
    'title' => $this->faker->title,
    'content' => $this->faker->paragraph,
    ];
    }
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $user = User::factory()
    ->has(Post::factory()->count(3))
    ->create();
  • Answer:
    <?php
    $user = User::factory()
    // 在建立該 user model 的同時, 建立三個 Post model
    // 須事先 define User hasMany Post 的 relation
    ->has(Post::factory()->count(3))
    ->create();
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $user = User::factory()
    ->has(Post::factory()->count(3), 'posts')
    ->create();
  • Answer:
    <?php
    $user = User::factory()
    // create User 的同時也 create 三筆 Post, 須事先定義
    // User hasMany Post relation
    // 帶入 'posts' 為特別指定, 若無指定 Laravel 會使用自己的 convention 尋找
    ->has(Post::factory()->count(3), 'posts')
    ->create();
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $user = User::factory()
    ->has(
    Post::factory()
    ->count(3)
    ->state(function (array $attributes, User $user) {
    return ['user_type' => $user->type];
    })
    )
    ->create();
  • Answer:
    <?php
    $user = User::factory()
    ->has(
    Post::factory()
    ->count(3)
    // 使用 state method 在 Post model 中定義額外與 User model 相關的資訊
    ->state(function (array $attributes, User $user) {
    return ['user_type' => $user->type];
    })
    )
    ->create();
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $user = User::factory()
    ->hasPosts(3)
    ->create();
  • Answer:
    使用 factory’s magic relationship methods, 在 create User model 的同時, 並 create 三個 Post relationship model
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $user = User::factory()
    ->hasPosts(3, [
    'published' => false,
    ])
    ->create();
  • Answer:
    使用 factory’s magic relationship methods, 在 create User model 的同時, 並 create 三個 Post relationship model, 並且額外帶入 attributes 覆蓋原本的
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $user = User::factory()
    ->hasPosts(3, function (array $attributes, User $user) {
    return ['user_type' => $user->type];
    })
    ->create();
  • Answer:
    使用 factory’s magic relationship methods, 在 create User model 的同時, 並 create 三個 Post relationship model, 因為會用到 User model 的內容來更新 Post model, 因此使用了 state method
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $posts = Post::factory()
    ->count(3)
    ->for(User::factory()->state([
    'name' => 'Jessica Archer',
    ]))
    ->create();
  • Answer:
    在 create 3 個 Post model 的同時, create 一個 belongsTo relation 的 User model, 並自定義 name column
    需事先在 Post model 定義與 User model 的 belongsTo relationship
以下的 Laravel Testing example code 的意思是?
  • Example:
    <?php
    $user = User::factory()->create();

    $posts = Post::factory()
    ->count(3)
    ->for($user)
    ->create();
  • Answer:
    在使用 Factory 建立 belongsTo relationship 時, 如果已有現成的 model, 可直接 pass 該 model as a parent
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $posts = Post::factory()
    ->count(3)
    ->forUser([
    'name' => 'Jessica Archer',
    ])
    ->create();
  • Answer:
    使用 Factory magic relationship method, create 3 個 Post model 並指定其 belongsTo User model, 並指定該 User model 的 name 為 Jessica Archer
以下的 Laravel Testing example code 的意思是?
  • Example:
    <?php
    $user = User::factory()
    ->has(Role::factory()->count(3))
    ->create();
  • Answer:
    也可使用 has() 來指定 relationship, 前提是要先在 model 定義好 relation
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $users = User::factory()
    ->hasAttached(
    Role::factory()->count(3),
    ['active' => true]
    )
    ->create();
  • Answer:
    使用 hasAttached method 來定義 pivot table 的 attribute
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $users = User::factory()
    ->hasAttached(
    Role::factory()
    ->count(3)
    ->state(function (array $attributes, User $user) {
    return ['name' => $user->name.' Role'];
    }),
    ['active' => true]
    )
    ->create();
  • Answer:
    <?php
    $users = User::factory()
    // 使用 hasAttached method 來定義 pivot table 的 attribute
    ->hasAttached(
    // 這邊具體行為, create 3 個 Role model, 並定義 name column 的 value
    // 為 $user->name.' Role', 會用到 User model, 所以使用 state method
    Role::factory()
    ->count(3)
    ->state(function (array $attributes, User $user) {
    return ['name' => $user->name.' Role'];
    }),
    // 這一行定義 pivot model 的 active column 的 value 為 true
    ['active' => true]
    )
    ->create();
以下的 Laravel Testing example code 的意思是?
  • Example:
    <?php
    $roles = Role::factory()->count(3)->create();

    $user = User::factory()
    ->count(3)
    ->hasAttached($roles, ['active' => true])
    ->create();
  • Answer:
    使用 hasAttached() 時, 也可直接帶入已經建立好的 models, 並定義 pivot table 上的值
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $users = User::factory()
    ->hasRoles(1, [
    'name' => 'Editor'
    ])
    ->create();
  • Answer:
    create User model 並且同步 create 1 個 Role model, User 與 Role model relationship 可以是 hasMany 或 manyToMany 或 morphMany, 並 overwrite name column 的 value 為 Editor
    Relationship 須事先定義
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    $comments = Comment::factory()->count(3)->for(
    Post::factory(), 'commentable'
    )->create();
  • Answer:
    使用 factory create 3 個 comment model, 並且 create 1 個 Post model, 彼此的 relationship 為 Comments morphTo Post
以下的 Laravel Testing example code 的意思是?
  • Example:
    <?php
    use App\Models\User;

    public function definition()
    {
    return [
    'user_id' => User::factory(),
    'title' => $this->faker->title,
    'content' => $this->faker->paragraph,
    ];
    }
  • Answer:
    在 Factory 內可直接定義 relationships
以下的 Laravel Testing example code 的意思是?
  • Example:
    <?php
    public function definition()
    {
    return [
    'user_id' => User::factory(),
    'user_type' => function (array $attributes) {
    return User::find($attributes['user_id'])->type;
    },
    'title' => $this->faker->title,
    'content' => $this->faker->paragraph,
    ];
    }
  • Answer:
    如果某個 attribute 的值取決於 relation model 的某個欄位, 可使用 closure, 並從 $attributes 取得當前已建立的 attributes 來進一步取得資訊
以下 Laravel 中, create hasMany 跟 morphMany 的 method 一樣嗎?

一樣

以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    public function run()
    {
    User::factory()
    ->times(50)
    ->hasPosts(1)
    ->create();
    }
  • Answer:
    利用 User factory create 50 個 User model, 並且每個 User model 各 create 一個 hasMany relationship Post model

# Calling Additional Seeders

以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    public function run()
    {
    $this->call([
    UserSeeder::class,
    PostSeeder::class,
    CommentSeeder::class,
    ]);
    }
  • Answer:
    在 database seeder 中, 定義要執行的 seeder, 當我下 php artisan db:seed 之後將會執行以上定義的 seeder


# Running Seeders

以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    php artisan db:seed

    php artisan db:seed --class=UserSeeder
  • Answer:
    <?php
    // 執行 database seeder, 會執行所有定義在 database seeder 中的動作
    php artisan db:seed

    // 只執行
    php artisan db:seed --class=UserSeeder
以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    <?php
    php artisan migrate:fresh --seed
  • Answer:
    migration drop 所有的 table 在執行 up 的同時, 執行 database seeder

# Forcing Seeders To Run In Production

以下 Laravel 中, 以下的 example code 意思是?
  • Example:
    php artisan db:seed --force
  • Answer:
    在 production 中, Laravel 的保護機制, 當執行 php artisan db:seed 時會跳出詢問再確認的視窗, 若使用 flag --force 可略過此保護機制
Laravel - Eloquent ORM - Getting Started Laravel - Database - Migrations

留言

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×