在日常开发中,经常需要往数据库里填充数据,以便调试接口发现bug。Laravel自带的数据填充器seeder也十分好用,纯自动化填充,还支持一键回滚,只需在使用之前定义些方法即可,下面就介绍一下seeder普遍的用法。
版本
Laravel 5.2
流程介绍
- 生成Seeder填充类
- 按实际情况定义模型工厂
- 执行artisan命令自动化填充数据到数据库
- 回滚,恢复到实际生产环境
起步
首先利用artisan命令创建一个seeder类
1
| $ php artisan make:seeder TestSeeder
|
在/database/seeds/中,编写run方法
1 2 3 4 5 6 7 8 9
| class TestSeeder extends Seeder { public function run() { DB::table('YourTable')->insert([ 'name' => str_random(10) ]); } }
|
如上,只需把插入语句写进seeder类的run方法即可。上面的例子是往YourTable表里插入一条记录,但是这是我们日常都是大批量填充数据的,此时就需要用到模型工厂。
一个模型单角色定义
模型工厂的定义脚本在/database/factories/ModelFactory.php,我们只需脚本里定义好模型,然后就可以在seeder类里使用了。
1 2 3 4 5 6 7 8 9
| $factory->define(App\YourModel::class,function (Faker\Generator $faker){ return [ 'name' => $faker->name, 'email' => $faker->email, 'password' => str_random(10), 'remember_token' => str_random(10), 'admin' => true, ]; });
|
Faker是专门生成假数据的包(GITHUB地址),这样至少生成的假数据也好看点而不是一堆乱码数字对吧。
一个模型多角色定义
除了用define字段定义模型外,我们常常还用到defineAs,因为通常一个模型(表)里面,存在这不同角色,比如User表里可以存在普通用户或者管理员两种角色,这时可以用defineAs
1 2 3 4 5 6 7 8 9 10
| $factory->defineAs(App\YourModel::class,'admin',function (Faker\Generator $faker){ return [ 'name' => $faker->name, 'email' => $faker->email, 'password' => str_random(10), 'remember_token' => str_random(10), 'is_admin' => true, ]; });
|
生产
这样我们就定义好了一个模型工厂,要工厂生产产品就需要用到Laravel的全局函数factory.生产产品的工厂一定要是定义过的才能用factory函数
1 2 3 4 5 6 7
| $obj=$factory->(App\YourModel::class)->make(); $collection=$factory->(App\YourModel::class,5)->make(); $collection=$factory->(App\YourModel::class,'admin',5)->make();
|
处理关联
数据库插入时也经常涉及关联,比如有两张表父表与子表,由于存在关联关系,设置了外键约束时,填充数据会很蛋疼,不过利用Laravel的eloquent使得填充数据十分方便,下面就讲一下如何操作
首先假设有两张表father和son,其中son的主键参照father表中的一个字段id
father的模型:
1 2 3 4 5 6 7
| class father extends Model { public function test(){ return $this->hasMany(\App\son:class,'id'); } }
|
son的模型细节我就忽略了,因为不是重点。接下来就要定义两个表的模型工厂
1 2 3 4 5 6 7 8 9 10 11
| $factory->define(App\father::class,function (){ return [ ] ; }); $factory->define(App\father::class,function (){ return [ ] ; });
|
然后就可以在seeder类的run方法里使用了
1 2 3 4 5
| factory(App\father::class,3) ->create() ->each(function ($obj){ $obj->test()->save(factory(App\son::class,2)->make()); });
|
就可以在你填充3个父亲的数据的同时,也为每个父亲填充2个与之关联的儿子
填充器模块化
一个填充器写N多个factory来填充数据,难免会看晕,因此我们需要将负责不同模型的生产分模块,划分成N多个子填充器
1 2 3 4 5 6 7
| public function run(){ Model::unguard(); $this->call(Test1Seeder::class); $this->call(Test2Seeder::class); Model::reguard(); }
|
unguard函数貌似是关闭自动填充的限制,reguard是恢复限制.还有一个函数
Model::truncate();用于放在成员函数里可以清空成员表数据,用来初始化填充还可以,不过有重要数据请备份。
最后一步
在编写好seeder之后,运行artisan即可进行填充
1 2
| php artisan db:seed php artisan db:seed --class=xxxxxSeeder // 你的填充类
|
一键回滚,重建数据库
1
| php artisan migrate:refresh --seed
|
坑点
因为运行artisan命令时本质上是用CLI,因此请开启proc_open,proc_get_status等系统调用函数,留意你的CLI所用的拓展是否有对应数据库的拓展,如果遇到CLI的坑可以去翻一些我前几天些的关于CLI的坑,遇到什么permission denied的给对应文件加上权限就好。
最后更新时间:
对本文内容有任何意见,建议,疑问etc,均可通过邮箱联系我,逗比博主尽最大努力回复O(∩_∩)O,如需转载(tan90°,不存在的(°Д°)),注明出处即可!