学习在 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 保留用于测试目的。

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

$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() 的意思是用英语说,构建一个用户类,我们想要 2 个用户,然后通过保存在数据库中来创建它们。

接下来是一个集合,它将遍历“每个”创建的用户。最后,在每个用户中保存一个与创建的用户相关的 issues。

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

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

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();

工厂 make 和 create 方法

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

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

结束

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

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

Eric L. Barnes photo

Eric 是 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

立即获得 Lucky - 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 应用程序添加评论

阅读文章