本文目录导读:

在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导入 | 执行快速 | 维护困难 | 静态数据 |
- 环境区分:开发/测试环境不同种子数据
- 幂等性:可重复执行不产生重复数据
- 事务处理:出错时自动回滚
- 数据量控制:按需生成,避免过大
- 版本控制:将种子数据纳入版本管理
选择哪种方案取决于你的项目需求,如果使用框架(如 Laravel、Symfony),建议使用框架自带的种子系统;如果是原生 PHP,建议使用 Faker + 自定义脚本来生成测试数据。