团队协作开发时,最容易出问题的往往不是业务代码,而是每个人本地那份“不太一样”的数据库结构。Laravel 的迁移和数据填充,正好解决了“表怎么统一创建”“测试数据怎么快速补齐”这两件麻烦事。下面就按实际使用顺序,把 Laravel 5.5 中从建表、跑迁移到批量生成中文假数据的流程完整过一遍,并把文中遇到的报错处理一并保留下来,方便你判断该怎么落地。
为什么要用迁移和填充
多人协作时,如果还靠手动执行 SQL、手动给同事补字段,数据库结构很容易出现偏差。迁移的作用,就是把数据表结构也纳入项目代码中管理:谁新增了字段、谁改了表结构,都通过迁移文件记录下来。
在线上部署时,这套方式同样省事。你不需要再手动导入数据库、手工改字段,直接运行迁移命令,就能让目标环境按项目约定创建或更新表结构。
而数据填充解决的是另一类问题:测试、联调、列表分页、搜索筛选这些场景,经常需要大量样例数据。与其一条条手造,不如交给 Seeder 和 Factory 一次性批量生成。
本文基于 Laravel 5.5,其他版本整体思路大同小异。
先把 students 表迁移出来
创建迁移文件
前提是已经配置好了数据库连接信息。先执行下面的 Artisan 命令:

php artisan make:migration create_students_table
命令执行后,会在 database/migrations/ 目录生成一个类似 2017_10_28_035802_create_students_table.php 的文件。接下来就在这个迁移文件里定义 students 表结构。
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
class CreateStudentsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// students为表名称
Schema::create('students', function (Blueprint $table) {
// 存储引擎
$table->engine = 'InnoDB';
// id自增
$table->increments('id');
// 学生名称
$table->string('name');
// 性别
$table->string('sex');
// 邮箱
$table->string('email');
// 喜爱的颜色
$table->string('favorite_color');
// 手机号
$table->string('phone');
// 地址
$table->string('addr');
// 自动维护时间戳
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('students');
}
}
这里的重点并不复杂:up() 负责创建表,down() 负责回滚时删除表。这样一来,数据结构本身也能跟着项目一起管理,而不是散落在某个人的本地 SQL 文件里。
如果需要更多字段类型或索引定义方式,可以继续查 Laravel 官方手册扩展用法。
运行迁移
表结构写好后,直接运行:

php artisan migrate
这条命令会执行 database/migrations/ 目录下的所有迁移文件。同时 Laravel 会自动创建一张 migrations 表,用来记录哪些迁移已经执行过,避免重复运行。
正常情况下,执行完成后,数据库里就会自动出现 students 表。
遇到 1071 错误怎么处理
如果迁移时出现下面这类错误:
[IlluminateDatabaseQueryException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was t
oo long; max key length is 767 bytes (SQL: alter table users add unique users_email_unique(email))
[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was t
oo long; max key length is 767 bytes
原因通常不是你刚写的 students 表本身,而是 database/migrations/ 目录里 Laravel 自带的用户表、密码重置表迁移文件也会一起执行。在当前环境下,索引长度和字符集配置不兼容,就可能报这个错。
原文给出的处理方式,是修改 config/database.php 里 MySQL 配置的字符集为 utf8:
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
改完后重新执行迁移即可。原文中提到的原因分析链接如下,保留供继续排查时使用:
https://segmentfault.com/a/1190000008416200
用 Seeder 和 Factory 批量造数据
先创建学生模型
要为 students 表批量生成数据,先在 app 目录下创建 Student.php 模型:
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
/**
* 学生模型
*/
class Student extends Model
{
}
模型本身很简单,主要是给后面的 Factory 和 Seeder 调用提供入口。
创建 Seeder 文件
接着生成一个学生表填充文件:
php artisan make:seed StudentsTableSeeder
这条命令会在 database/seeds/ 目录下生成 StudentsTableSeeder.php,内容可以改成这样:
<?php
use IlluminateDatabaseSeeder;
class StudentsTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
// 调用模型工厂 生成10000条数据
factory(AppStudent::class, 10000)->create();
}
}
这里的核心动作是:通过模型工厂一次性创建 10000 条数据。数量可以按你的测试需求调整,但原文这里保留的是 10000。
在 DatabaseSeeder 中注册
Seeder 文件生成后,还需要在 database/seeds/DatabaseSeeder.php 里显式调用它:
<?php
use IlluminateDatabaseSeeder;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
// 调用学生表填充文件
$this->call(StudentsTableSeeder::class);
}
}
这一步的意义是把入口统一交给 DatabaseSeeder 管理。后面执行 php artisan db:seed 时,Laravel 就会从这里开始往下调用。
创建模型工厂并定义数据格式
接下来创建工厂文件:
php artisan make:factory StudentsFactory -m Student
命令会在 database/factories/ 目录生成 StudentsFactory.php。然后在其中定义要填充的数据格式:
<?php
use FakerGenerator as Faker;
/* @var IlluminateDatabaseEloquentFactory $factory */
$factory->define(AppStudent::class, function (Faker $faker) {
$sex = rand(1, 1000);
return [
'name' => $faker->name,
'sex' => $sex % 2 == 0 ? '男' : '女',
'email' => $faker->unique()->safeEmail,
'favorite_color' => $faker->safeColorName,
'phone' => $faker->phoneNumber,
'addr' => $faker->address,
];
});
这段定义里,name、email、phone、addr 都交给 Faker 自动生成;sex 则通过随机数的奇偶来决定是“男”还是“女”。
如果你还想扩展更多字段格式,原文建议继续查阅:
vendor/fzaninotto/faker/src/Faker/Generator.php
让 Faker 生成中文测试数据
如果不做额外处理,Faker 默认生成的内容未必符合中文场景。要让名字、地址等字段尽量贴近中文环境,可以在 app/Providers/AppServiceProvider.php 的 boot() 中添加下面这段:
public function boot()
{
// 填充中文数据
$this->app->singleton(FakerGenerator::class, function () {
return FakerFactory::create('zh_CN');
});
}
这里的关键就是 FakerFactory::create('zh_CN')。配置完成后,Factory 在生成姓名、地址等字段时,就会尽量返回中文数据,而不是默认英文样式。
对于需要演示后台列表、搜索、中文排序、表单校验的项目来说,这一步很实用,因为它让测试数据更接近真实使用环境。
执行填充并检查结果
先刷新自动加载
开始填充前,原文建议先执行一次:
composer dump-autoload
这样可以重新加载你在 database/seeds/ 目录中新建的填充类,避免出现下面这个错误:
[ReflectionException]
Class StudentsTableSeeder does not exist
运行填充命令
确认没问题后,再执行真正的填充命令:
php artisan db:seed
因为这里一次要写入 10000 条数据,所以耗时可能会稍长一些。执行过程中,你甚至可以刷新数据库,看到记录一条条增加。
最终结果是什么样
如果前面的步骤都没有报错,那么 students 表里就应该已经有数据了。原文给出的结果示例如下,可以看到姓名、性别、邮箱、颜色、手机号、地址以及时间戳都已经被批量生成:
id | name | sex | email | favorite_color | phone | addr | created_at |updated_at
---|------|------|------|------|------|------|------|------|------|---
10000 |谈英 |男 |cum_et@example.com |白色 |17642207316 |贵阳海陵区 |2017-10-28 05:19:10 |2017-10-28 05:19:10
9999 |汤淑珍 |男 |qlaudantium@example.net |黑色 |18239453935 |南宁友好区 |2017-10-28 05:19:10 |2017-10-28 05:19:10
9998 |贾春梅 |男 |ea35@example.com |粟色 |17103645128 |长沙萧山区 |2017-10-28 05:19:10 |2017-10-28 05:19:10
9997 |季志明 |男 |cdeleniti@example.com |灰色 |17002359608 |天津花溪区 |2017-10-28 05:19:10 |2017-10-28 05:19:10
9996 |成燕 |男 |aspernatur.aut@example.com |黄色 |17181193397 |贵阳锡山区 2017-10-28 05:19:|10 |2017-10-28 05:19:10
9995 |米博 |男 |reprehenderit_autem@example.com |紫 |17187328893 |广州东丽区 |2017-10-28 05:19:10 |2017-10-28 05:19:10
9994 |兰淑兰 |女 |et_ea@example.com |绿色 |18592254358 |兰州经济开发新区 |2017-10-28 05:19:10 |2017-10-28 05:19:10
9993 |乐瑶 |女 |vel.vitae@example.org |藏青 |15891490007 |香港龙潭区 2017-10-28 05:19:|10 |2017-10-28 05:19:10
9992 |叶志新 |女 |lcumque@example.net |藏青 |15564391466 |北京高明区 |2017-10-28 05:19:10 |2017-10-28 05:19:10
9991 |胥杨 |男 |voluptatem00@example.com |黄色 |17097722096 |郑州新城区 |2017-10-28 05:19:10 |2017-10-28 05:19:10
9990 |凌敏 |女 |magni22@example.org |鲜绿色 |13021578051 |杭州涪城区 |2017-10-28 05:19:10 |2017-10-28 05:19:10
9989 |席建 |女 |fugiat_accusantium@example.net |紫 |18070573726 |南昌海陵区 |2017-10-28 05:19:10 |2017-10-28 05:19:10
9988 |聂新华 |女 |debitis_sapiente@example.com |水色 |17004061646 |成都南长区 |2017-10-28 05:19:10 |2017-10-28 05:19:10
到这里,迁移负责“把表建出来”,Seeder、Factory 和 Faker 负责“把数据补进去”,一套完整流程就跑通了。对于团队协作、初始化环境、联调测试和后台开发,这比手工建表和手工造数据稳定得多,也更容易复用。









