本文目录导读:

在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中不仅用于测试,也是开发阶段填充数据的最佳实践,可以大幅提高开发效率。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播