Ray Lee | 李宗叡
Learn or Die
Published in
20 min readDec 9, 2020

--

Photo by Markus Spiske on Unsplash

# 前言

我喜歡使用 Laravel 開發的感覺, 除了開發快速, 程式碼簡潔且優雅之外, Laravel 框架本身也是一個很好的學習參照物。 本篇主要將官方文件重點整理成 Q&A 的形式呈現, 原子化的概念, 這方式並不適用於每個人, 但若對你有幫助, 我會很開心。

# 版本

Laravel 8.x

# 目錄

Laravel — 官方文件原子化翻譯 — 目錄

# 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 中, 以下的 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 中, 以下的 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 中, 以下的 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 中, 以下的 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 中, 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 可略過此保護機制

--

--

Ray Lee | 李宗叡
Learn or Die

It's Ray. I do both backend and frontend, but more focus on backend. I like coding, and would like to see the whole picture of a product.