在 Laravel 中学习使用模型工厂

发布时间:作者:

Learn to use Model Factories in Laravel image

Laravel 5.1 带有一个名为模型工厂的功能,旨在让您快速构建“假”模型。

这些模型工厂有几个用例,其中两个最大的用例是测试和数据库播种。让我们通过构建一个小型的虚构应用程序来更深入地了解这个功能。

开始

假设您被 LEMON 定制房屋建造商雇用,他们需要一种方法让客户在房屋建成后提交故障单。对于像 LEMON 这样的名字,您知道他们会遇到很多问题,因此您的任务是简化此流程。

为了创建绝对最低限度的功能,我们可以使用用户表来代表客户,并创建一个新的问题表。因此让我们开始构建它们。

创建一个新应用程序

laravel new lemon-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 文件,如果您不想使用默认的 Homestead,可以更改您的数据库名称。

现在让我们填写迁移文件。

创建迁移

打开 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();
});
}

在这个迁移中,我们只是向用户表添加一个 user_id 关系,以及问题主题和描述,以便客户可以提供详细的报告。

现在运行迁移

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” 模型作为第一个参数,然后是一个回调函数,该函数定义了插入到各个列中的数据。这个回调函数还注入了一个名为 Faker 的库,它是一个用于生成虚拟数据的 PHP 库。Faker 功能强大,可以用于多种不同的字段类型。以下是一些示例,展示了代码中显示的字段类型

请注意:如果您的应用程序要发送真实的电子邮件,那么您应该使用 $faker->safeEmail 而不是 ->email。原因是 ->email 可能生成真实的电子邮件,而 safeEmail 使用 example.org,该域名根据 RFC2606 为测试目的而保留。

现在,让我们为 Issues 模型创建一个新的工厂。以下是完成的代码

$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 类,我们想要 2 个用户,然后将它们创建出来,并保存到数据库中。

接下来是一个集合的 each 函数,它将对每个创建的用户运行。最后,在每个用户中保存一个与创建用户相关联的问题。

运行 Artisan 命令

$ 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 模型工厂进行测试

使用模型工厂的一个主要好处是,我们现在可以在我们的测试套件中使用它们。为我们的 Issues 创建一个新的测试

php artisan make:test IssuesTest

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

<?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 特性,以便每个测试都被包装在事务中。在 testIssueCreation 方法中,我们添加了我们的模型工厂,并使用了一个新功能。create 方法传递了一个包含列名和预设值的数组。这允许您覆盖原始模型工厂定义中存储的内容。

对于实际的测试,我们使用了 seeInDatabase 方法,顾名思义,它搜索数据库,如果找到给定的列和值,则返回绿色。

现在我们已经了解了这些模型工厂如何在播种和测试中使用,让我们看看它提供的一些有用功能。

其他模型工厂功能

在为与 LEMON 房地产的第一次会议做准备时,您注意到您的原始设置存在一个问题。您忘记添加一种将问题标记为已解决的方法。这将很尴尬。

多种工厂类型

在为 “已完成” 字段添加了新的迁移之后,需要调整模型工厂,但如果有一个单独的模型工厂,这样就可以轻松地创建一个已完成的问题,将会很方便。定义一个新的工厂,如下所示

$factory->defineAs(App\Issues::class, 'completed', function ($faker) use ($factory) {
$issue = $factory->raw(App\Issues::class);
 
return array_merge($issue, ['completed' => true]);
});

这个工厂使用一个名称作为第二个参数,在本例中为 “completed”,并在回调函数中,我们创建了一个新的问题,并将我们的已完成列合并到其中。

如果您现在想创建一个 “已完成” 的问题,只需要运行以下命令

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

Factory make 方法与 create 方法

在最后一个示例中,您可能已经注意到我调用了 ->make() 而不是 ->create(),就像之前做的那样。这两个方法做了两件不同的事情,“create” 尝试将数据存储到数据库中,这与在 Eloquent 中保存数据相同。另一方面,make 创建模型,但不会实际插入。如果您熟悉 Eloquent,它相当于

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

结束

如你所见,模型工厂是 Laravel 中一个强大的功能,有助于简化测试和数据库播种。

此外,请查看 v5.3.17 中的 Laravel 模型工厂状态

Eric L. Barnes photo

埃里克是 Laravel News 的创始人,自 2012 年以来一直报道 Laravel。

Cube

Laravel 新闻

加入 40,000 多名其他开发人员,永不错过新的技巧、教程等。

Laravel Forge logo

Laravel Forge

轻松创建和管理您的服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。 使用 AI、自动完成和对本地和生产环境的即时反馈进行调试。

Tinkerwell
No Compromises logo

绝不妥协

Joel 和 Aaron,两位来自 No Compromises 播客的经验丰富的开发者,现已可供您的 Laravel 项目聘用。 ⬧ 固定费率为每月 7500 美元。 ⬧ 没有冗长的销售流程。 ⬧ 没有合同。 ⬧ 100% 返款保证。

绝不妥协
Kirschbaum logo

Kirschbaum

提供创新和稳定性,确保您的 Web 应用程序成功。

Kirschbaum
Shift logo

Shift

运行旧版 Laravel? 立即自动升级 Laravel 并进行代码现代化,以保持您的应用程序更新。

Shift
Bacancy logo

Bacancy

使用经验丰富的 Laravel 开发人员 (拥有 4-6 年经验) 为您的项目增效,每月只需 2500 美元。 获得 160 小时的专业知识和 15 天免费试用。 立即安排通话!

Bacancy
Lucky Media logo

Lucky Media

立即获得幸运 - 拥有十年以上经验,是 Laravel 开发的理想选择!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel 电子商务

Laravel 的电子商务。 一个开源软件包,将现代无头电子商务功能的力量带入 Laravel。

Lunar: Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 工作板

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS 启动工具包

SaaSykit 是一个 Laravel SaaS 启动工具包,包含运行现代 SaaS 所需的所有功能。 支付、漂亮的结账、管理面板、用户仪表板、身份验证、现成的组件、统计信息、博客、文档等。

SaaSykit: Laravel SaaS 启动工具包
Rector logo

Rector

您无缝升级 Laravel 的合作伙伴,降低成本,并加速创新,为成功的公司提供服务

Rector
MongoDB logo

MongoDB

通过 MongoDB 和 Laravel 的强大集成增强您的 PHP 应用程序,使开发人员能够轻松高效地构建应用程序。 支持事务、搜索、分析和移动用例,同时使用熟悉的 Eloquent API。 了解 MongoDB 的灵活的现代数据库如何改变您的 Laravel 应用程序。

MongoDB
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的零依赖输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

将 Swagger UI 添加到您的 Laravel 应用程序

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的精确 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel Prompts 构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速模糊网站搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 包在 Laravel 应用程序中添加评论

阅读文章