PHP种子数据怎么填充

wen PHP项目 2

本文目录导读:

PHP种子数据怎么填充

  1. 使用数据库迁移工具(推荐)
  2. 自定义 PHP 脚本方法
  3. 使用 Faker 库生成假数据
  4. SQL 文件导入方式
  5. 更高级:使用 Phinx 迁移工具
  6. 最佳实践建议
  7. 推荐的依赖库
  8. 执行方式对比

在PHP中填充种子数据(Seed Data)有多种方法,我来详细介绍几种常见的方案:

使用数据库迁移工具(推荐)

Laravel 方式

// database/seeders/UserSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Post;
class UserSeeder extends Seeder
{
    public function run()
    {
        User::create([
            'name' => 'Admin User',
            'email' => 'admin@example.com',
            'password' => bcrypt('password'),
        ]);
        // 批量创建
        User::factory()
            ->count(50)
            ->has(Post::factory()->count(3))
            ->create();
    }
}
// 运行种子数据
php artisan db:seed
php artisan db:seed --class=UserSeeder

自定义 PHP 脚本方法

简单数据库填充脚本

<?php
// seed.php
class DatabaseSeeder {
    private $pdo;
    public function __construct($host, $dbname, $user, $pass) {
        $this->pdo = new PDO(
            "mysql:host=$host;dbname=$dbname;charset=utf8mb4",
            $user,
            $pass,
            [
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
            ]
        );
    }
    public function seedUsers($count = 100) {
        $stmt = $this->pdo->prepare(
            "INSERT INTO users (name, email, created_at) VALUES (?, ?, ?)"
        );
        for ($i = 0; $i < $count; $i++) {
            $stmt->execute([
                $this->generateName(),
                $this->generateEmail(),
                date('Y-m-d H:i:s')
            ]);
        }
        echo "Seeded $count users\n";
    }
    private function generateName() {
        $firstNames = ['John', 'Jane', 'Mike', 'Sarah', 'Tom'];
        $lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones'];
        return $firstNames[array_rand($firstNames)] . ' ' . 
               $lastNames[array_rand($lastNames)];
    }
    private function generateEmail() {
        $domains = ['gmail.com', 'yahoo.com', 'hotmail.com'];
        $email = strtolower(str_replace(' ', '.', $this->generateName()));
        return $email . '@' . $domains[array_rand($domains)];
    }
}
// 使用示例
$seeder = new DatabaseSeeder('localhost', 'myapp', 'root', 'password');
$seeder->seedUsers(50);

使用 Faker 库生成假数据

<?php
// 需要先安装 composer require fakerphp/faker
require_once 'vendor/autoload.php';
$faker = Faker\Factory::create();
$pdo = new PDO('mysql:host=localhost;dbname=myapp', 'root', 'password');
// 生成用户数据
$stmt = $pdo->prepare("INSERT INTO users 
    (name, email, phone, address, created_at) 
    VALUES (?, ?, ?, ?, ?)");
for ($i = 0; $i < 1000; $i++) {
    $stmt->execute([
        $faker->name(),
        $faker->unique()->safeEmail(),
        $faker->phoneNumber(),
        $faker->address(),
        $faker->dateTimeBetween('-1 year', 'now')->format('Y-m-d H:i:s')
    ]);
}
// 生成关联数据
$stmt = $pdo->prepare("INSERT INTO orders 
    (user_id, product_id, quantity, total, created_at) 
    VALUES (?, ?, ?, ?, ?)");
for ($i = 0; $i < 5000; $i++) {
    $stmt->execute([
        $faker->numberBetween(1, 1000),  // 随机用户ID
        $faker->numberBetween(1, 100),   // 随机产品ID
        $faker->numberBetween(1, 5),     // 数量
        $faker->randomFloat(2, 10, 1000),// 金额
        $faker->dateTimeBetween('-6 months', 'now')->format('Y-m-d H:i:s')
    ]);
}

SQL 文件导入方式

<?php
// import_seed.php
class SeedImporter {
    private $pdo;
    public function __construct($host, $dbname, $user, $pass) {
        $this->pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
    }
    public function importFromFile($filePath) {
        $sql = file_get_contents($filePath);
        // 按分号分割执行(注意处理存储过程等特殊情况)
        $statements = array_filter(
            array_map('trim', explode(';', $sql))
        );
        foreach ($statements as $statement) {
            $this->pdo->exec($statement);
        }
        echo "Import completed from: $filePath\n";
    }
}
// 使用
$importer = new SeedImporter('localhost', 'myapp', 'root', 'password');
$importer->importFromFile('./seed_data.sql');

更高级:使用 Phinx 迁移工具

// db/migrations/20240101000000_seed_users.php
<?php
use Phinx\Migration\AbstractMigration;
class SeedUsers extends AbstractMigration
{
    public function up()
    {
        $data = [];
        for ($i = 0; $i < 20; $i++) {
            $data[] = [
                'name' => "User{$i}",
                'email' => "user{$i}@example.com",
                'status' => 'active',
                'created_at' => date('Y-m-d H:i:s')
            ];
        }
        $this->table('users')
             ->insert($data)
             ->saveData();
    }
    public function down()
    {
        $this->execute('DELETE FROM users WHERE id > 0');
    }
}

最佳实践建议

<?php
// SeedManager.php - 统一管理种子数据
class SeedManager {
    private $pdo;
    private $faker;
    public function __construct($config) {
        $this->initDatabase($config);
        $this->faker = Faker\Factory::create();
    }
    // 主入口
    public function run() {
        echo "开始填充种子数据...\n";
        try {
            $this->seedUsers();
            $this->seedCategories();
            $this->seedProducts();
            $this->seedOrders();
            echo "所有种子数据填充完成!\n";
        } catch (Exception $e) {
            $this->rollback();
            throw $e;
        }
    }
    private function initDatabase($config) {
        $this->pdo = new PDO(
            "mysql:host={$config['host']};dbname={$config['dbname']};charset=utf8mb4",
            $config['user'],
            $config['pass']
        );
        $this->pdo->beginTransaction();
    }
    private function seedUsers() {
        $stmt = $this->pdo->prepare(
            "INSERT INTO users (name, email, password, role) VALUES (?, ?, ?, ?)"
        );
        // 创建管理员
        $stmt->execute(['Admin', 'admin@example.com', password_hash('admin123', PASSWORD_BCRYPT), 'admin']);
        // 创建普通用户
        for ($i = 0; $i < 50; $i++) {
            $stmt->execute([
                $this->faker->name(),
                $this->faker->unique()->email(),
                password_hash('password123', PASSWORD_BCRYPT),
                'user'
            ]);
        }
        echo "✓ 用户数据填充完成\n";
    }
    private function rollback() {
        if ($this->pdo->inTransaction()) {
            $this->pdo->rollBack();
            echo "✗ 出错,已回滚事务\n";
        }
    }
}
// 使用
$config = [
    'host' => 'localhost',
    'dbname' => 'myapp',
    'user' => 'root',
    'pass' => 'password'
];
$manager = new SeedManager($config);
$manager->run();

推荐的依赖库

// composer.json
{
    "require-dev": {
        "fakerphp/faker": "^1.23",
        "phpunit/phpunit": "^10.0"
    }
}

执行方式对比

方式 优点 缺点 适用场景
框架迁移 集成度高 依赖框架 使用主流框架
自定义脚本 灵活可控 需手动实现 小型项目
Faker 数据真实 需额外依赖 测试和开发
SQL导入 执行快速 维护困难 静态数据
  1. 环境区分:开发/测试环境不同种子数据
  2. 幂等性:可重复执行不产生重复数据
  3. 事务处理:出错时自动回滚
  4. 数据量控制:按需生成,避免过大
  5. 版本控制:将种子数据纳入版本管理

选择哪种方案取决于你的项目需求,如果使用框架(如 Laravel、Symfony),建议使用框架自带的种子系统;如果是原生 PHP,建议使用 Faker + 自定义脚本来生成测试数据。

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