在 Laravel 项目开发中,数据库表结构可以通过 Migration 管理,而一些基础数据、测试数据和初始化账号,则更适合通过 Seeder 处理。比如后台管理员账号、默认分类、系统配置、测试文章、演示用户等,都可以写成数据填充脚本,后续在本地、测试环境或新服务器部署时快速生成。
一、Laravel Seeder 是什么
Seeder 是 Laravel 提供的数据填充工具,用来向数据库中写入预设数据。它常用于项目初始化、测试数据生成和演示环境准备。
常见使用场景包括:
- 初始化后台管理员账号;
- 创建默认角色和权限;
- 写入系统基础配置;
- 生成测试用户;
- 生成文章、分类、标签等演示数据;
- 为开发和测试环境准备模拟数据。
Seeder 和 Migration 的职责不同。Migration 负责创建和修改数据表结构,Seeder 负责向表中写入数据。一个管“表怎么建”,一个管“表里先放什么数据”。
二、创建 Seeder 文件
在 Laravel 项目根目录执行以下命令:
php artisan make:seeder AdminUserSeeder
执行后会在 database/seeders 目录下生成文件:
database/seeders/AdminUserSeeder.php
基础结构如下:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class AdminUserSeeder extends Seeder
{
public function run(): void
{
//
}
}
所有需要写入数据库的逻辑,都可以放在 run() 方法中。
三、写入一个后台管理员账号
假设项目中使用 Laravel 默认的 users 表,可以在 Seeder 中创建一个管理员账号:
<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
class AdminUserSeeder extends Seeder
{
public function run(): void
{
User::updateOrCreate(
['email' => 'admin@example.com'],
[
'name' => 'Admin',
'password' => Hash::make('ChangeMe123456'),
]
);
}
}
这里使用 updateOrCreate(),可以避免重复执行 Seeder 时生成多个相同账号。如果邮箱已存在,就更新对应数据;如果不存在,就创建新账号。
密码必须使用 Hash::make() 加密,不要把明文密码直接写入数据库。
四、注册 Seeder
Laravel 默认有一个总入口文件:
database/seeders/DatabaseSeeder.php
可以在其中调用刚创建的 Seeder:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run(): void
{
$this->call([
AdminUserSeeder::class,
]);
}
}
这样执行总的数据填充命令时,Laravel 就会自动运行 AdminUserSeeder。
五、执行数据填充命令
运行全部 Seeder:
php artisan db:seed
只运行指定 Seeder:
php artisan db:seed --class=AdminUserSeeder
如果需要重建数据表并重新填充测试数据,可以在本地开发环境执行:
php artisan migrate:fresh --seed
需要注意,migrate:fresh 会删除所有表并重新执行迁移,可能造成数据丢失。这个命令通常只适合本地或测试环境,不建议在生产环境随意执行。
六、创建默认分类数据
除了管理员账号,Seeder 也适合写入默认分类。
例如创建文章分类:
<?php
namespace Database\Seeders;
use App\Models\Category;
use Illuminate\Database\Seeder;
class CategorySeeder extends Seeder
{
public function run(): void
{
$categories = [
['name' => '开发教程', 'slug' => 'development'],
['name' => '服务器教程', 'slug' => 'server'],
['name' => '软件使用教程', 'slug' => 'software'],
];
foreach ($categories as $category) {
Category::updateOrCreate(
['slug' => $category['slug']],
$category
);
}
}
}
然后在 DatabaseSeeder 中注册:
public function run(): void
{
$this->call([
AdminUserSeeder::class,
CategorySeeder::class,
]);
}
这种写法适合系统必须存在的基础数据,例如默认分类、默认角色、默认配置等。
七、配合 Factory 生成测试数据
如果需要生成大量测试数据,Seeder 可以配合 Factory 使用。
先创建模型工厂:
php artisan make:factory PostFactory --model=Post
示例 Factory:
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory
{
public function definition(): array
{
return [
'title' => fake()->sentence(),
'content' => fake()->paragraphs(3, true),
'status' => 1,
];
}
}
在 Seeder 中调用:
<?php
namespace Database\Seeders;
use App\Models\Post;
use Illuminate\Database\Seeder;
class PostSeeder extends Seeder
{
public function run(): void
{
Post::factory()->count(50)->create();
}
}
这样可以快速生成 50 条测试文章。对于后台列表、分页、搜索、筛选和性能测试来说,这种方式非常方便。
八、给测试数据建立关联关系
实际项目中的数据通常不是孤立的。例如文章需要关联分类和作者。
示例:
use App\Models\Category;
use App\Models\Post;
use App\Models\User;
public function run(): void
{
$user = User::factory()->create();
$category = Category::create([
'name' => 'Laravel教程',
'slug' => 'laravel',
]);
Post::factory()
->count(20)
->create([
'user_id' => $user->id,
'category_id' => $category->id,
]);
}
如果模型关系已经写好,也可以通过关系创建数据。这样生成的数据更接近真实业务场景。
九、区分开发环境和生产环境
Seeder 在不同环境中的用途不同。
开发环境中,可以大量生成测试用户、文章、订单和评论,用来模拟真实数据。
测试环境中,可以生成固定数据,方便自动化测试。
生产环境中,Seeder 更适合初始化必要数据,例如管理员账号、系统配置、角色权限和默认分类,不建议随意生成演示内容。
如果某个 Seeder 只应在本地运行,可以加环境判断:
public function run(): void
{
if (! app()->environment('local')) {
return;
}
// 只在本地生成测试数据
}
这样可以避免测试数据误入生产环境。
十、生产环境使用 Seeder 的注意事项
生产环境执行 Seeder 前,需要特别谨慎。
建议遵循以下原则:
- 不要生成大量测试数据;
- 不要覆盖真实用户数据;
- 管理员默认密码上线后必须修改;
- 使用
updateOrCreate()或firstOrCreate()避免重复数据; - 执行前确认当前环境;
- 重要操作前备份数据库;
- 不要把真实密钥、私密配置和敏感账号写死在代码中。
如果需要初始化配置,可以优先使用环境变量或后台配置表,不要把生产敏感信息直接写进 Seeder 文件。
十一、常见问题
Seeder 和 Migration 有什么区别?
Migration 用来管理数据库表结构,例如建表、改字段、加索引。Seeder 用来写入数据,例如初始化账号、默认分类和测试内容。两者通常配合使用。
Seeder 可以重复执行吗?
可以,但要看写法。如果使用 create(),重复执行可能生成重复数据。如果使用 updateOrCreate() 或 firstOrCreate(),会更适合重复执行。
生产环境可以执行 db:seed 吗?
可以,但只建议执行经过确认的初始化 Seeder。不要在生产环境运行包含大量测试数据的 Seeder。
Factory 和 Seeder 是什么关系?
Factory 负责定义一条模拟数据怎么生成,Seeder 负责决定生成哪些数据、生成多少条、是否建立关联。大量测试数据通常由两者配合完成。
默认管理员账号应该写进 Seeder 吗?
可以用于初始化,但默认密码必须及时修改。更稳妥的方式是通过环境变量传入初始邮箱和密码,避免固定密码长期存在于代码中。

