本文目录导读:

在Laravel中,工厂模式(Factory Pattern)是用于生成测试数据的强大工具,以下是完整的实现方案:
基础使用
生成单个模型数据
use App\Models\User; // 创建单条数据(不保存) $user = User::factory()->make(); // 创建单条数据(保存到数据库) $user = User::factory()->create(); // 创建多条数据 $users = User::factory()->count(10)->create();
创建自定义工厂
生成工厂文件
php artisan make:factory UserFactory --model=User
定义工厂结构
<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class UserFactory extends Factory
{
protected $model = User::class;
public function definition()
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => bcrypt('password'),
'remember_token' => Str::random(10),
];
}
// 自定义状态
public function admin()
{
return $this->state(function (array $attributes) {
return [
'role' => 'admin',
'is_active' => true,
];
});
}
public function unverified()
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
}
关联模型工厂
一对多关系
// PostFactory.php
public function definition()
{
return [
'user_id' => User::factory(),
'title' => fake()->sentence(),
'content' => fake()->paragraph(),
];
}
多对多关系
// 创建带有标签的文章
$post = Post::factory()
->has(Tag::factory()->count(3))
->create();
// 或者使用关系
public function tags()
{
return $this->belongsToMany(Tag::class);
}
高级用法
动态属性
// 使用回调动态生成数据
User::factory()->create([
'name' => '特定名称',
'email' => function () {
return fake()->unique()->safeEmail();
}
]);
序列化状态
// 交替使用不同的状态
$users = User::factory()
->count(10)
->sequence(
['role' => 'admin'],
['role' => 'editor'],
['role' => 'user'],
)
->create();
批量创建带关系的数据
// 创建用户并关联文章
User::factory()
->count(5)
->has(Post::factory()->count(3))
->create();
// 更复杂的关系
$user = User::factory()
->has(Profile::factory())
->hasPosts(3)
->hasComments(5)
->create();
测试中使用
public function test_user_can_create_post()
{
// 创建测试用户
$user = User::factory()->admin()->create();
// 创建文章
$post = Post::factory()->create([
'user_id' => $user->id
]);
// 验证
$this->assertDatabaseHas('posts', [
'id' => $post->id,
'user_id' => $user->id
]);
}
Seeder中使用
// DatabaseSeeder.php
public function run()
{
// 创建10个用户
User::factory()->count(10)->create();
// 创建带有特定关系的复合数据
User::factory()
->count(5)
->create()
->each(function ($user) {
Post::factory()
->count(fake()->numberBetween(1, 5))
->create(['user_id' => $user->id]);
});
}
性能优化技巧
// 大量数据创建时使用chunk
collect(range(1, 1000))->chunk(100)->each(function ($chunk) {
User::factory()->count($chunk->count())->create();
});
// 使用数据库事务提高性能
DB::transaction(function () {
User::factory()->count(1000)->create();
});
常用数据类型生成
class ProductFactory extends Factory
{
public function definition()
{
return [
'sku' => fake()->unique()->ean13(),
'name' => fake()->words(3, true),
'price' => fake()->randomFloat(2, 100, 1000),
'quantity' => fake()->numberBetween(0, 100),
'description' => fake()->paragraphs(2, true),
'manufacturer' => fake()->company(),
'date_available' => fake()->dateTimeThisYear(),
'status' => fake()->randomElement(['active', 'inactive']),
];
}
}
自定义数据生成器
// 创建自定义数据提供器
use Faker\Provider\Base as FakerProvider;
class CustomProvider extends FakerProvider
{
public function customId()
{
return 'CUS-' . $this->generator->unique()->numberBetween(100000, 999999);
}
}
// 在工厂中使用
public function definition()
{
$this->faker->addProvider(new CustomProvider($this->faker));
return [
'custom_id' => $this->faker->customId(),
];
}
注意事项
- 唯一性约束:使用
unique()方法确保数据不重复 - 性能考虑:大批量生成数据时注意内存使用
- 优先级:显式传入的数据优先于工厂定义
- 测试隔离:测试中使用
RefreshDatabasetrait
use Illuminate\Foundation\Testing\RefreshDatabase;
class ProductTest extends TestCase
{
use RefreshDatabase;
public function test_create_product()
{
$product = Product::factory()->create();
$this->assertDatabaseHas('products', ['id' => $product->id]);
}
}
工厂模式在Laravel中不仅用于测试,也是开发阶段填充数据的最佳实践,可以大幅提高开发效率。