调用Factory时Laravel记录被删除
Posted
技术标签:
【中文标题】调用Factory时Laravel记录被删除【英文标题】:Laravel record being deleted when calling Factory 【发布时间】:2019-06-02 19:17:18 【问题描述】:我有两个表 - Roles 和 Users。在 Roles 内部,我只有一条记录。
id: 1, name: Employee, timestamps: blahblah
奇怪的是,每当我调用我的用户工厂(它有一个字段 role_id 的外键)时,它都会删除 Roles 表中的记录。它也使工厂实例化的创建失败,说 role_id 外键约束失败。我不知道为什么会这样。
这是用户工厂的代码。我已经对值进行了硬编码,直到我弄明白为止。
$factory->define(App\User::class, function (Faker $faker)
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => Hash::make("12341234"),
'remember_token' => str_random(10),
'company_id' => 1,
'role_id' => 1,
];
);
还有错误:
Doctrine\DBAL\Driver\PDOException: SQLSTATE[23000]: 完整性 违反约束:1452 无法添加或更新子行:外国 键约束失败 (
app
.users
, CONSTRAINTusers_role_id_foreign
外键 (role_id
) 引用roles
(id
))
任何帮助将不胜感激。
【问题讨论】:
这个错误说明找不到角色表。此工厂代码在执行角色表之前执行。如果可以使用外键,只需更改数据库表的执行顺序即可。 你执行的命令是什么? 不知道你说的执行顺序是什么意思。我知道它可以找到角色表,因为我可以在 Tinker 中创建和细化角色记录。 【参考方案1】:您的外键验证似乎是您错误所说的问题。
给定的上下文你的 role_id 似乎是外键,你只是传递一个你永远不会工作的任意值。
要解决此问题,您必须创建一个创建新角色的工厂方法并执行以下操作
$factory->define(App\User::class, function (Faker $faker)
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => Hash::make("12341234"),
'remember_token' => str_random(10),
'company_id' => 1,
'role_id' => factory(Role::class)->create()->id,
];
);
PS 确保您的批量分配包含 role_id
【讨论】:
但是在这种假设情况下,如果... factory(Role::class)->create()->id == 1,为什么不将其替换为 1(即当前在表中的记录)有效吗? 你听说过YAGNI
吗?其次,您应该能够像factory(Role::class)->create(['role_id' =>1)->id
一样传递role_id。你用你的模型工厂做什么?看看laravel-news.com/learn-to-use-model-factories-in-laravel-5-1
我在特性测试中使用工厂 - 从未听说过 YAGNI,但这只是标准 TDD。我正在使用模型工厂作为用户执行各种功能。这里的主要怪异再次是调用工厂删除角色表中具有匹配 id 的记录,然后抛出错误。
当你运行测试时,laravel 使用RefreshDatabase
trait,它会在你每次运行测试时刷新数据库。确保您有不同的数据库用于测试或内存存储。看看这个***.com/questions/49503921/… 如何设置你的测试
希望我的评论有意义。我推荐拉拉卡斯特。学习 laravel 的所有内容并使用 laravel 进行测试的好地方。祝你好运【参考方案2】:
虽然我无法弄清楚与此相关的确切奇怪之处,但我相信它与 phpUnit 的数据库配置有关。我在我的 phpunit.xml 中添加了以下几行,解决了这个问题。
还值得一提的是,role 实体已被删除,因为测试使用的是 RefreshDatabase。
<env name="DB_CONNECTION" value="sqlite" />
<env name="DB_DATABASE" value=":memory:" />
【讨论】:
@usrNotFound 指出您通常使用不同的数据库进行测试。 是的 - 我假设 phpunit 的默认数据库配置与 Laravel 的不同,这可能是导致问题的原因。话虽如此,外国约束为何特别失败仍然令人困惑。 它与硬编码 vs 工厂生成的 role_id 无关。以上是关于调用Factory时Laravel记录被删除的主要内容,如果未能解决你的问题,请参考以下文章
在 Factory Laravel 中创建 JWTAuth 令牌
在运行 laravel phpunit testcase 时,我在 Model.php 第 1249 行收到错误“调用 null 上的成员函数 connection()”