写一个模型工厂类php,Laravel 的模型工厂使用小结

2206b1b3141d675949cb44a83307ef17.png

Laravel 5.1 之后新增了一个名为模型工厂的功能,用来快速构建一个「假」的模型。

让我们构建一个小小的应用程序来深入了解一下这个功能。这些有两个最大的测试和数据填充的用例。

开始

现在假设我们要做一个简单的报修系统,用来收集用户的问题反馈。报修的用户使用自带的 users 表,然后再创建一个新的问题表。

安装一个新的应用程序:

laravel new support

接下来,用 artisan 命令来创建我们的问题表的模型和迁移。 使用 make:model 命令传递 -m 或 -migration 来创建。

php artisan make:model Issues -m

这条命令会在 app/ 中生成 Issues.php 和 database/migrations/ 中生成 create_issues_table 迁移文件。

现在我们要在 app/User.php 模型文件中关联用户表与问题表之间的一对多关系:

public function issues()

{

return $this->hasMany('issues');

}

如果你不想使用默认的配置,就编辑 .env 并更改数据库信息。

现在我们来填写这些迁移文件。

创建迁移

打开 database/migrations/datetime_create_issues_table.php 并如下修改 up 方法:

public function up()

{

Schema::create('issues', function (Blueprint $table) {

$table->increments('id');

$table->integer('user_id');

$table->string('subject');

$table->text('description');

$table->timestamps();

});

}

现在运行迁移:

php artisan migrate

它应该输出以下内容:

Migration table created successfully.

Migrated: 2014_10_12_000000_create_users_table

Migrated: 2014_10_12_100000_create_password_resets_table

Migrated: 2015_10_03_141020_create_issues_table

接下来,我们来填充数据,以便我们有数据来进行其他操作。

建立数据填充

数据填充是一种用程序运行的方式将数据插入到数据库中,其优点就是可以将虚拟数据快速地导入到应用程序中。 可以节省不少捏数据的时间呢!

先为用户表填充数据。 用以下命令生成编写数据填充的文件:

php artisan make:seeder UserTableSeeder

当然,问题表的数据填充也要创建

php artisan make:seeder IssueTableSeeder

现在打开 database/seeds/DatabaseSeeder.php 文件,并修改 run 方法:

public function run()

{

Model::unguard();

$this->call(UserTableSeeder::class);

$this->call(IssueTableSeeder::class);

Model::reguard();

}

记得么?用户和问题是有关联关系的,也就是说我们不能就这样运行这些填充方法。接下来我们看看如何用模型工厂来向程序说明他们之间的关联关系。

创建模型工厂

以前填充数据的时候,可以使用 Eloquent 或 Laravel的查询构建器。 而现在,引入模型工厂之后,就可以使用它们来构建可用于测试的填充的数据和「虚拟」模型。

打开 database/factories/ModelFactory.php,你会看到下面这些:

$factory->define(App\User::class, function (Faker\Generator $faker) {

return [

'name' => $faker->name,

'email' => $faker->email,

'password' => bcrypt(str_random(10)),

'remember_token' => str_random(10),

];

});

解释一下,我们把 App\User::class 模型作为 define() 的第一个参数,然后定义了字段中的数据的回调。 这个回调中引入了 Faker,它是一个会生成假数据的 PHP 库,功能强大,可用于多种不同的场类型。 这是一个示例:

$fake->name – “John Smith”

$faker->email – “tkshlerin@collins.com”

注意:如果你的程序要发送真实的电子邮件,那就要使用 $faker->safeEmail。 原因是 $faker->email 可能会生成一个真实的电子邮件,而 safeEmail 以测试目的使用了由 RFC2606 保留的 example.org 。

现在,为问题模型创建一个新的工厂:

$factory->define(App\Issues::class, function (Faker\Generator $faker) {

return [

'subject' => $faker->sentence(5),

'description' => $faker->text(),

];

});

现在来看看数据填充的类,并使用这些工厂生成数据。

打开 UserTableSeeder 并修改 run 方法:

public function run()

{

factory(App\User::class, 2)->create()->each(function($u) {

$u->issues()->save(factory(App\Issues::class)->make());

});

}

现在简单讲一下这段代码的作用:在 factory(App\User::class, 2)->create() 这句中写明了,我们需要构建 User 类,在数据库中创建两个用户。然后用 collection 的 each 方法为每个被创建的用户建立关联的问题数据。

运行迁移填充的命令:

$ php artisan migrate --seed

Migrated: 2014_10_12_000000_create_users_table

Migrated: 2014_10_12_100000_create_password_resets_table

Migrated: 2015_10_03_141020_create_issues_table

Seeded: UserTableSeeder

现在我们数据库里面就有我们要的表,表中包含了模型工厂为我们生成的数据。

用 Laravel 模型工厂进行测试

拥有模型工厂的主要好处是我们可以在测试套件中使用这些。 为我们的问题创建一个新的测试:

php artisan make:test IssuesTest

打开 tests/IssuesTest.php 并添加一个新的方法来测试问题的创建:

use Illuminate\Foundation\Testing\WithoutMiddleware;

use Illuminate\Foundation\Testing\DatabaseMigrations;

use Illuminate\Foundation\Testing\DatabaseTransactions;

class IssuesTest extends TestCase

{

use DatabaseTransactions;

public function testIssueCreation()

{

factory(App\Issues::class)->create([

'subject' => 'NAIL POPS!'

]);

$this->seeInDatabase('issues', ['subject' => 'NAIL POPS!']);

}

}

在这个测试中,我们使用 DatabaseTransactions trait,以便每个测试都被包装在一个事务中。我们在 testIssueCreation 中写测试添加问题的功能。 create 方法传递关联数组,能覆盖原始模型工厂定义中存储的内容。然后我们使用 seeInDatabase 去搜索数据库中是否存在给定的字段和值。

看到这里你应该知道怎么用模型工厂去测试和填充数据了吧?不懂就翻回去多看几遍,懂了的话,来看看其他一些进阶的功能!

其他特点

现在有件尴尬的事情,就是我忘了在数据库中添加一个字段用于写入问题的解决方法。

多工厂类型

在为这个字段 completed 添加新的迁移之后,我们需要对模型工厂进行调整,定义一个这样的新工厂:

$factory->defineAs(App\Issues::class, 'completed', function ($faker) use ($factory) {

$issue = $factory->raw(App\Issues::class);

return array_merge($issue, ['completed' => true]);

});

使用数据库的字段 completed 作为第二个参数,在回调中,我们创建了一个新的问题,并将 completed 合并这个问题里面。

也就是说,如果你想要创建一个「已完成」的问题,那就要这样子写:

$completedIssue = factory(App\Issue::class, 'completed')->make();

make VS create

你可能已经注意到,上面调用了 ->make() 而不是 ->create()。 这两种方法做了两件不同的事情:create 尝试将其存储在数据库中,跟 Eloquent 中的 save 方法一样。 而 make 仅仅只是创建了模型,不会向数据库插入数据。 如果你熟悉 Eloquent,make 执行起来就像这样:

$issue = new \App\Issue(['subject' => 'My Subject']);

扩展

在 Laravel 5.3.17 中你可以在模型工厂定义不同的「状态」。

现在我们要为用户定义身份:

$factory->define(App\User::class, function (Faker\Generator $faker) {

return [

'name' => $faker->name,

'email' => $faker->safeEmail,

];

});

这个用户可以是管理员:

$factory->state(\App\User::class, 'admin', function (\Faker\Generator $faker) {

return [

'is_admin' => 1,

];

});

或者是主席:

$factory->state(\App\User::class, 'moderator', function (\Faker\Generator $faker) {

return [

'is_moderator' => 1,

];

});

然后你可以这样调用:

// Create 5 users

factory(\App\User::class, 5)->create();

// Create 5 Admins

factory(\App\User::class, 5)->states('admin')->create();

// Create 5 Moderators

factory(\App\User::class, 5)->states('moderator')->create();

// Create 5 Admins that are also moderators

factory(\App\User::class, 5)->states('admin', 'moderator')->create();

本作品采用《CC 协议》,转载必须注明作者和本文链接

Stay Hungry, Stay Foolish.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值