本文目录导读:

在Laravel中,数据填充是开发过程中非常重要的一环,我来详细讲解如何编写数据填充器。
基础数据填充器
创建填充器
# 创建基本填充器 php artisan make:seeder UserSeeder # 创建带模型的填充器 php artisan make:seeder ProductSeeder --model=Product # 创建所有表的填充器(生产环境常用) php artisan make:seeder DatabaseSeeder
基础填充器示例
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
class UserSeeder extends Seeder
{
public function run(): void
{
// 单条插入
User::create([
'name' => 'Admin',
'email' => 'admin@example.com',
'password' => bcrypt('password'),
]);
// 多条插入
$users = [
['name' => 'User1', 'email' => 'user1@example.com', 'password' => bcrypt('secret')],
['name' => 'User2', 'email' => 'user2@example.com', 'password' => bcrypt('secret')],
];
foreach ($users as $user) {
User::create($user);
}
}
}
使用工厂(Factory)
创建工厂
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(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => bcrypt('password'),
'remember_token' => Str::random(10),
];
}
// 自定义状态
public function admin(): static
{
return $this->state(fn (array $attributes) => [
'is_admin' => true,
]);
}
}
在填充器中使用工厂
<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Seeder;
class UserSeeder extends Seeder
{
public function run(): void
{
// 创建10个用户
User::factory()->count(10)->create();
// 创建特殊用户
User::factory()->admin()->create();
// 批量创建并指定字段
User::factory()->count(5)->create([
'role' => 'editor'
]);
}
}
处理关联数据
<?php
namespace Database\Seeders;
use App\Models\User;
use App\Models\Post;
use App\Models\Comment;
use Illuminate\Database\Seeder;
class PostSeeder extends Seeder
{
public function run(): void
{
// 创建用户及其关联文章
User::factory()
->has(
Post::factory()
->count(3)
->has(Comment::factory()->count(5))
)
->create();
// 使用关联方法
User::all()->each(function ($user) {
Post::factory()
->count(2)
->for($user)
->create()
->each(function ($post) {
Comment::factory()->count(3)->create([
'post_id' => $post->id,
'user_id' => User::inRandomOrder()->first()->id,
]);
});
});
}
}
复杂数据填充
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Product;
use App\Models\Category;
class ProductSeeder extends Seeder
{
public function run(): void
{
// 使用循环和随机数据
for ($i = 0; $i < 50; $i++) {
Product::create([
'name' => "Product {$i}",
'sku' => 'SKU-' . str_pad($i, 4, '0', STR_PAD_LEFT),
'price' => rand(10, 1000) / 10,
'stock' => rand(0, 100),
'category_id' => Category::inRandomOrder()->first()->id,
'is_active' => rand(0, 1) === 1,
'description' => "Description for product {$i}",
'specifications' => json_encode([
'weight' => rand(1, 10) . 'kg',
'color' => ['红', '蓝', '绿'][rand(0, 2)],
'material' => '塑料'
]),
]);
}
// 批量插入(大数据量时效率更高)
$products = [];
for ($i = 100; $i < 200; $i++) {
$products[] = [
'name' => "Bulk Product {$i}",
'price' => rand(10, 500),
'created_at' => now(),
'updated_at' => now(),
];
}
DB::table('products')->insert($products);
}
}
数据填充策略
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run(): void
{
// 分步执行
$this->call([
UserSeeder::class,
CategorySeeder::class,
ProductSeeder::class,
OrderSeeder::class,
]);
// 或条件执行
if (app()->environment('production')) {
$this->call(ProductionSeeders::class);
} else {
$this->call(DevelopmentSeeders::class);
}
}
}
高级技巧
数据集修改器
<?php
namespace Database\Factories;
class ProductFactory extends Factory
{
public function definition(): array
{
return [
'name' => $this->faker->word,
'price' => $this->faker->randomFloat(2, 10, 1000),
'image' => $this->faker->imageUrl(),
];
}
// 特定状态
public function expensive(): static
{
return $this->state(function (array $attributes) {
return ['price' => fake()->randomFloat(2, 5000, 10000)];
});
}
}
使用模型事件
// 在填充器中使用模型事件
Model::creating(function ($model) {
$model->uuid = Str::uuid();
});
执行数据填充
# 运行所有填充器
php artisan db:seed
# 运行特定填充器
php artisan db:seed --class=UserSeeder
# 初始化后填充
php artisan migrate:fresh --seed
# 指定环境
php artisan db:seed --env=testing
# 在代码中执行
DB::table('users')->truncate(); // 清空表
Artisan::call('db:seed', ['--class' => 'UserSeeder', '--force' => true]);
注意事项
避免重复数据
<?php
namespace Database\Seeders;
class UserSeeder extends Seeder
{
public function run(): void
{
// 使用 firstOrCreate 或 updateOrCreate
User::firstOrCreate(
['email' => 'admin@example.com'],
['name' => 'Admin', 'password' => bcrypt('password')]
);
}
}
性能优化
// 大数据量时使用 chunk
Product::chunk(100, function ($products) {
foreach ($products as $product) {
// 处理数据
}
});
// 使用 DB::table 直接插入
DB::table('products')->insert($data);
生产环境安全
// 在填充器中检查环境
if (app()->isProduction() && !$this->command->confirm('是否在正式环境运行?')) {
$this->command->error('已取消');
return;
}
这些是Laravel数据填充的主要方法和最佳实践,根据项目需求选择合适的策略,可以高效地完成数据初始化工作。