PHP项目Laravel数据填充如何编写

wen PHP项目 5

本文目录导读:

PHP项目Laravel数据填充如何编写

  1. 基础数据填充器
  2. 使用工厂(Factory)
  3. 处理关联数据
  4. 复杂数据填充
  5. 数据填充策略
  6. 高级技巧
  7. 执行数据填充
  8. 注意事项
  9. 生产环境安全

在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数据填充的主要方法和最佳实践,根据项目需求选择合适的策略,可以高效地完成数据初始化工作。

抱歉,评论功能暂时关闭!