はじめに
久しぶりの投稿でQiitaCLIのコマンドを忘れてしまったちびまろです。
早速ですがみなさん、Laravelは好きですか?
僕は好きです!大好きです!
プライベートで少しずつ勉強しているのでまだまだひよっこですが、新しく機能について理解が深まるともっともっとと気持ちが昂ります!
理由?分かりません。好きなもんは好きなんです!
題名にあるとおり、今回はLaravelのFactoryについて書かせていただければと思います。
私自身何となく「テストデータを大量に作るやつ」くらいのイメージで使ってましたが、ちゃんと理解して使おうと思い立ったので調べてみることにしました。
Factoryとは
データベースにテスト用のダミーデータを簡単に作成するための設計書です。
勉強している最中にイメージ的にmigrationと似ているなと感じました。
Factoryはテストや開発中に大量のデータを扱いたいときに便利な機能です。
本物のデータを用意しなくてもFactoryとFaker(PHPライブラリ)を組み合わせることで簡単にランダムなデータを生成することができます。
この機能を使うことで手動で何十、何百ものデータを作成する手間を省くことができます。
めちゃくちゃ便利...!
Laravelの中にdatabaseディレクトリがあり、その中にFactoryクラスが存在します。
database
├── database.sqlite
├── factories
│ └── UserFactory.php
├── migrations
│ ├── 0001_01_01_000000_create_users_table.php
│ ├── 0001_01_01_000001_create_cache_table.php
│ └── 0001_01_01_000002_create_jobs_table.php
└── seeders
└── DatabaseSeeder.php
Factoryの作成方法
Factoryを新たに作成することも可能です。
Laravelにはartisanコマンドと呼ばれるLaravel独自のコマンドがあります。
こちらのコマンドで新しいFactoryを作成できます。
php artisan make:factory factoryName
このコマンドを実行すると、database/factories
ディレクトリ内に新しいFactoryクラスが生成されます。
factoryNameで作成するFactoryクラスの名前を指定できます。
例
php artisan make:factory PostFactory
このコマンドを実行すると、database/factories/PostFactory.php
が生成されます。
database
├── factories
│ ├── PostFactory.php
│ └── UserFactory.php
... 省略
このファイル内でモデルのデフォルトの属性値を定義します。
Factoryの中身について
今回はLaravelインストール時にデフォルトで作成されるUserFactory.php
の中身を見ていきましょう。
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
*/
class UserFactory extends Factory
{
/**
* The current password being used by the factory.
*/
protected static ?string $password;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*/
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
}
各コードの意味
ズラーっとコードがたくさんあると少々混乱するかもしれませんが、1つずつに絞ってみていくとそれほど難しくもありません。
すぐ理解できなくてもそんなもんです!
ということで1つずつ説明していきます。
protected static ?string $password;
プログラミングしてる人ならよく見るコードの形ですね!
「最もprotectedで、最もstaticで、そして最もstringな宣言でいかせていただきます。」(何言ってんだ)
すみません、ふざけすぎました。
protected
プロパティやメソッド、定数などのアクセス権の制御を示すキーワードです。
public、protected、privateのいずれかを指定することで定義が可能です。
protected
を宣言されたものは、そのクラス自身やそのクラスを継承したクラス、親クラスからのみアクセスが可能です。
それ以外の場所からは直接アクセスすることはできません。
つまり、今回でいうとUserFactory.php
の中でのみ、この$password
に値を代入したり、値を参照したりすることが可能です。
static
クラスプロパティ、またはメソッドに対してstatic
を宣言すると、クラスのインスタンス化を行う必要がなくなります。
インスタンスを使用しなくても、クラスを直接指定することで変数やインスタンスを呼び出せるようにできます。
どうやら擬似変数である$this
については、staticを宣言されたメソッドの内部から利用することが出来ないらしいです。
?string
型宣言でstring
は見たことありますが、先頭にある?
って何ですかね。
公式ドキュメントに記載がありました。
パラメータや戻り値の型宣言をする際に、型の前に?
をつけるとnullableであることを指定できる。
クエスチョンマークの後ろで指定した型だけでなく、nullも渡せるようになります。
何でもそうですが、便利〜!と安易に考えて使用する場面をミスるとバグに繋がりかねない機能だなと思いました。
使用する際は注意したいですね!!
definitionメソッド
メソッドのすぐ上にコメントが書いてありますね。
Define the model's default state.
日本語訳は「モデルのデフォルト状態を定義する。」です。
これはFactoryで生成されるユーザーの「初期データ」を設定するためのメソッドです。
このメソッドは下記のようなコードを実行すると呼び出され、生成するユーザーのデフォルトの属性を指定します。
User::factory()->make()
User::factory()->create()
Userモデルと紐づいており、下記コードのreturnで指定されているname
やemail
、password
などはusersテーブルのカラムと紐づいています。
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
];
}
fake()->???()
とすることで、PHPのライブラリであるFakerを使ってダミーデータを生成して!と指示することができます。
name
ユーザーの名前が登録されるカラム。
fake()->name()
を使うことでランダムな名前が生成されます。
ユーザーのメールアドレスが登録されるカラム。
ランダムで一意なメールアドレスを生成
fake()->unique()->safeEmail()
ではここでUserFactory.php
の中にあるpassword
で何をしているのかを見ていきましょう。
'password' => static::$password ??= Hash::make('password'),
初めてUserFactoryが実行される時、左側のstatic::$password
の状態はnullです。
static::$password
がnullの場合にHash::make('password')
が実行されます。
1回目の実行
Hash::make('password')
が実行されます。
2回目以降
static::$password
に格納されたデータが再利用されます。
ではいつ格納されるのか!!!!
ここで注目すべきものが??=
です。
これは null合体代入演算子 と呼ばれる機能で左辺の変数がnullの場合に限り、右辺の値を代入することができる演算子です。
処理の流れ
- 1回目の実行では、
static::$password
がnullなので、Hash...
が実行されます -
Hash::make('password')
が実行されると同時に??=
によって、static::$password
に結果が代入されます
※static::$password
はstaticプロパティであるため、このクラス全体から使えます - 2回目以降の実行では、
static::$password
に値が入っているため、??=
による代入は実行されません。1回目の実行でstatic::$password
に代入されたハッシュ化パスワードがをのまま使われます
unverifiedメソッド
ECサイトとかのユーザーを新規登録するとき、入力したメールアドレス宛に確認メールが届きますよね?
このメソッドはそれ関連で、ユーザーがメールを未確認の状態で作成されるように設定します。
確認メールを承認していないユーザーが必要な場合もあるため、その際にこのunverified
メソッドを使います。
下記ロジックのようにこのunverified
メソッドを使うことができます。
$user = User::factory()->unverified()->create()
上記が実行されると、usersテーブルのemail_verified_at
にnullが設定されたテストデータが登録されます。
まとめ
- Fakerはダミーデータ作成のためのPHPライブラリ
- Factoryはダミーデータ作成のための設計書(定義書)
- 基本的には
definition()
でテーブルに対するテストデータを定義する -
Null合体演算子
と呼ばれる演算子がある
なんとなくテストデータを作成するためのデータと認識していたレベルでしたが、今回改めて調べた結果理解度がかなりアップしましたね!
他にもなんとなくで使用している機能があるのでどんどん調べていこうと思いました!
ごっつ楽しくなりそうですねww
ではみなさん!今日もプログラミングを楽しんでいきましょう!!