在初步搭建好网站后台后,需要添加一定量的数据到数据库来验证一下,此时就可以使用factory来批量添加数据,
为了便于理解,本篇博客从数据工厂的使用开始介绍,倒序到模型的定义,建议配合laravel官方文档模型工厂部分阅读
在项目文件夹下database/seeds/DatabaseSeeder.php中的run方法下:
public function run()
{
//数据工厂制造测试数据
factory(App\Article::class, 50)->create()->each(function ($article) {
$article->categories()->sync($article->category_id);
});
}
以上代码表示,用factory工厂下的Article模型创建了50个article对象,存储到数据库中。创建的同时,每个article对象和category的关系也存储到了中间表article_category中。
在terminal执行以下命令:
php artisan migrate --seed
就成功将测试数据写入到了数据库中。
再上一步中,我们成功将数据创建并写入到了数据库中,那么article包含哪些属性呢?此时就要看,你在数据工厂下的模型内定义了哪些字段。也就是说,你想要创建工厂对象,就需要先建立工厂模型。工厂模型需要在database/factories目录下定义。
在terminal中使用如下命令,框架将会自动为我们在该目录下建立模型文件(此处建议使用驼峰命名法):
art make:factory ArticleFactory
自动建立的模型文件如下:
define(Model::class, function (Faker $faker) {
return [
//
];
});
此时就自定义了一个工厂模型,define()的两个参数,第一个参数是项目的模型,第二个参数是一个闭包函数,你可以返回模型中所有属性的默认测试值,我在其中重写了article的属性。
我定义的FactoryArticle模型如下:
define(\App\Article::class, function (Faker $faker) {
//随机取一个月以内的时间.
$time = $faker->dateTimeThisMonth();
return [
//
'title' => $faker->name,
'body' => $faker->paragraph,
'description' => $faker->sentence,
'category_id' => function () {
return factory(App\Category::class)->create()->id;
},
'image_url' => ' /img/default.jpg',
'author_id' => function () {
return factory(App\User::class)->create()->id;
},
'author' => function (array $article) {
return App\User::find($article['author_id'])->name;
},
'created_at' => $time,
'updated_at' => $time,
];
});
在闭包内会接收到 Faker PHP 函数库的实例,它可以让你很方便的生成各种随机数据以进行测试。$faker实例能够调用的属性,也就是可以生成的数据内容,并非由用户自定义,需要查阅github上 PHP library Faker的Formatters部分。链接如下:
github.com/fzaninotto/Faker#formatters
在上面的示例代码中,category_id定义的闭包函数,表示用CategoryFactory模型(也需要事先定义好CategoryFactory模型)创建了一个新的category对象,写入到数据库中,并将新创建的category的id字段的值,返回给article对象的category_id属性。下面的author_id字段同理(先创建user对象写入数据库,再返回其id给author_id属性)。
author字段的属性,则是在users表中根据user和的article的一对多关系,按照当前article对象的author_id字段查询到所属User的记录设置。关于此处的查询逻辑,可以参照laravel官方文档5.5的模型关联部分。
你可以把数组传递至 create 方法,随时重写工厂模型的属性,操作如下:
$user = factory(App\User::class)->create([
'name' => 'Abigail',
]);